অস্তিত্ব 1 বা অস্তিত্ব ব্যবহার করে সাবকিউরি *


89

আমি আমার অস্তিত্বের চেকগুলি এভাবে লিখতাম:

IF EXISTS (SELECT * FROM TABLE WHERE Columns=@Filters)
BEGIN
   UPDATE TABLE SET ColumnsX=ValuesX WHERE Where Columns=@Filters
END

আগের জীবনের ডিবিএর একজন আমাকে বলেছিল যে আমি যখন একটি EXISTSধারা করি তখন SELECT 1পরিবর্তে ব্যবহার করুন useSELECT *

IF EXISTS (SELECT 1 FROM TABLE WHERE Columns=@Filters)
BEGIN
   UPDATE TABLE SET ColumnsX=ValuesX WHERE Columns=@Filters
END

এটি কি আসলেই কোনও পার্থক্য করে?


4
আপনি অস্তিত্ব ভুলে গেছেন (নির্বাচন করুন নীল থেকে ...)। এটি সম্প্রতি বিটিডব্লিউ
ওএমজি পনিস

17
পিএস একটি নতুন ডিবিএ পেতে। আইটি, বিশেষত ডাটাবেস ব্যবস্থাপনায় কুসংস্কারের কোনও স্থান নেই (প্রাক্তন ডিবিএ থেকে !!!)
ম্যাট রোগিশ

উত্তর:


136

না, এসকিউএল সার্ভারটি স্মার্ট এবং এটি একটি অস্তিত্বের জন্য ব্যবহৃত হচ্ছে তা জানে এবং সিস্টেমে কোনও ডেটা ফেরত দেয় না।

কোথ মাইক্রোসফ্ট: http://technet.microsoft.com/en-us/library/ms189259.aspx?ppud=4

অস্তিত্বের দ্বারা প্রবর্তিত সাবকোয়ারির নির্বাচনের তালিকাটিতে প্রায়শই একটি তারকাচিহ্ন (*) থাকে। কলামের নাম তালিকাভুক্ত করার কোনও কারণ নেই কারণ আপনি কেবল পরীক্ষা করছেন যে সাবকোয়ারিতে উল্লিখিত শর্তগুলি পূরণ করে এমন সারিগুলি বিদ্যমান কিনা।

নিজেকে যাচাই করতে নিম্নলিখিত চালানোর চেষ্টা করুন:

SELECT whatever
  FROM yourtable
 WHERE EXISTS( SELECT 1/0
                 FROM someothertable 
                WHERE a_valid_clause )

এটি যদি নির্বাচিত তালিকার সাথে আসলে কিছু করছে তবে এটি শূন্য ত্রুটির দ্বারা একটি ডিভ ফেলে দেবে। এটা হয় না।

সম্পাদনা: দ্রষ্টব্য, এসকিউএল স্ট্যান্ডার্ডটি আসলে এটি সম্পর্কে কথা বলে।

এএনএসআই এসকিউএল 1992 স্ট্যান্ডার্ড, পৃষ্ঠা 191 http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt

3) কেস:
ক) যদি <select list>"*" কেবলমাত্র একটিতে থাকে <subquery> যা তাত্ক্ষণিকভাবে একটিতে অন্তর্ভুক্ত থাকে <exists predicate>তবে এটি একটি স্বেচ্ছাসেবী <select list> হিসাবে সমান ।<value expression><literal>


4
EXISTS1/0 এর কৌশলটি এটি পর্যন্ত প্রসারিতও হতে পারে SELECT 1 WHERE EXISTS(SELECT 1/0)... দ্বিতীয় ধরণের SELECTকোনও FROMধারা না থাকায় এক ধাপ আরও বিমূর্ত মনে হয়
কেন

4
@ হোয়াথেক - বা SELECT COUNT(*) WHERE EXISTS(SELECT 1/0)। এসকিউএল সার্ভারে একটি SELECTব্যতীত FROMএমন আচরণ করা হয় যেন এটি একটি একক সারি টেবিল অ্যাক্সেস করে (যেমন dualঅন্যান্য আরডিবিএমএসের টেবিল থেকে নির্বাচন করার অনুরূপ )
মার্টিন স্মিথ

@ মার্টিনস্মিথ চিয়ারস - সুতরাং মুল বক্তব্যটি হ'ল SELECT1 সারি টেবিলটি 1/0আবর্জনা সত্ত্বেও অন্য কিছু করার আগে 1 টি সারি টেবিল তৈরি করে EXISTS?
কেন

এটি কি সবসময়ই ছিল, নাকি এটি একটি অপ্টিমাইজেশন যা এসকিউএল সার্ভারের একটি বিশেষ সংস্করণে প্রবর্তিত হয়েছিল?
মার্টিন ব্রাউন

4
@ মার্টিনস্মিথ টিআইএল "কোথ" এটি ঠিক করার জন্য ধন্যবাদ।
গুড়বিন্দর সিং

114

এই ভ্রান্ত ধারণার কারণ সম্ভবত এটি বিশ্বাস করে যে এটি সমস্ত কলামটি পড়ে শেষ করবে। এটি সহজেই দেখা যায় যে এটি এমন নয়।

CREATE TABLE T
(
X INT PRIMARY KEY,
Y INT,
Z CHAR(8000)
)

CREATE NONCLUSTERED INDEX NarrowIndex ON T(Y)

IF EXISTS (SELECT * FROM T)
    PRINT 'Y'

পরিকল্পনা দেয়

পরিকল্পনা

এটি দেখায় যে এসকিউএল সার্ভার সূচকটি সমস্ত কলামকে অন্তর্ভুক্ত করে না সত্ত্বেও ফলাফল যাচাই করার জন্য উপলব্ধ সংকীর্ণ সূচকটি ব্যবহার করতে সক্ষম হয়েছিল। সূচক অ্যাক্সেসটি একটি অর্ধ যোগদানের অপারেটরের নিচে রয়েছে যার অর্থ এটি প্রথম সারিতে ফিরে আসার সাথে সাথে স্ক্যান করা বন্ধ করতে পারে।

সুতরাং এটি পরিষ্কার যে উপরোক্ত বিশ্বাসটি ভুল।

তবে ক্যোরি অপটিমাইজার টিমের কনর কানিংহ্যাম এখানে ব্যাখ্যা করেছেন যে তিনি সাধারণত SELECT 1এই ক্ষেত্রে ব্যবহার করেন কারণ এটি ক্যোয়ারীর সংকলনে সামান্য পারফরম্যান্সের পার্থক্য করতে পারে ।

কিউপি *পাইপলাইনের প্রথম দিকে সমস্তগুলি গ্রহণ এবং প্রসারিত করবে এবং তাদেরকে বস্তুর সাথে আবদ্ধ করবে (এই ক্ষেত্রে, কলামগুলির তালিকা)। এটি কোয়েরির প্রকৃতির কারণে বিনা শর্তযুক্ত কলামগুলি সরিয়ে ফেলবে।

সুতরাং EXISTSএই মত একটি সহজ subquery জন্য :

SELECT col1 FROM MyTable WHERE EXISTS (SELECT * FROM Table2 WHERE MyTable.col1=Table2.col2)এর *সম্ভাব্য কয়েকটি বড় কলামের তালিকায় প্রসারিত হবে এবং তারপরে এটি নির্ধারিত হবে যে এর শব্দার্থতত্ত্বগুলিতে col EXISTSকলামগুলির কোনওটির প্রয়োজন নেই, সুতরাং মূলত সেগুলি সমস্তই সরানো যেতে পারে।

" SELECT 1" কোয়েরি সংকলনের সময় সেই টেবিলের জন্য কোনও বিনাবিহীন মেটাডেটা পরীক্ষা করা এড়ানো হবে।

তবে রানটাইমের সময় ক্যোয়ারির দুটি রূপ একরকম হবে এবং অভিন্ন রানটাইম থাকবে।

আমি খালি টেবিলে বিভিন্ন সংখ্যক কলাম সহ এই কোয়েরিটি প্রকাশ করার সম্ভাব্য চারটি উপায় পরীক্ষা করেছি। SELECT 1বনাম SELECT *বনাম SELECT Primary_Keyবনাম SELECT Other_Not_Null_Column

আমি একটি লুপের সাহায্যে ক্যুরিগুলি চালিয়েছি OPTION (RECOMPILE)এবং প্রতি সেকেন্ডে মৃত্যুদন্ড কার্যকর করার সংখ্যাটি পরিমাপ করেছি। নীচে ফলাফল

এখানে চিত্র বর্ণনা লিখুন

+-------------+----------+---------+---------+--------------+
| Num of Cols |    *     |    1    |   PK    | Not Null col |
+-------------+----------+---------+---------+--------------+
| 2           | 2043.5   | 2043.25 | 2073.5  | 2067.5       |
| 4           | 2038.75  | 2041.25 | 2067.5  | 2067.5       |
| 8           | 2015.75  | 2017    | 2059.75 | 2059         |
| 16          | 2005.75  | 2005.25 | 2025.25 | 2035.75      |
| 32          | 1963.25  | 1967.25 | 2001.25 | 1992.75      |
| 64          | 1903     | 1904    | 1936.25 | 1939.75      |
| 128         | 1778.75  | 1779.75 | 1799    | 1806.75      |
| 256         | 1530.75  | 1526.5  | 1542.75 | 1541.25      |
| 512         | 1195     | 1189.75 | 1203.75 | 1198.5       |
| 1024        | 694.75   | 697     | 699     | 699.25       |
+-------------+----------+---------+---------+--------------+
| Total       | 17169.25 | 17171   | 17408   | 17408        |
+-------------+----------+---------+---------+--------------+

যেমন দেখা যায় যে SELECT 1এবং SELECT *উভয় পদ্ধতির মধ্যে পার্থক্য নগণ্য। যদিও SELECT Not Null colএবং SELECT PKকিছুটা দ্রুত উপস্থিত হয়।

সারণীর কলামগুলির সংখ্যা বাড়ার সাথে সাথে চারটি প্রশ্নেরই কর্মক্ষমতা হ্রাস পায়।

টেবিলটি খালি হওয়ায় এই সম্পর্কটি কলাম মেটাডেটার পরিমাণের দ্বারা কেবল বর্ণনামূলক বলে মনে হয়। জন্য COUNT(1)এটি দেখতে যে এই পুনর্লিখিত পরার সহজ COUNT(*)নীচের থেকে প্রক্রিয়ায় কিছু সময়ে।

SET SHOWPLAN_TEXT ON;

GO

SELECT COUNT(1)
FROM master..spt_values

যা নিম্নলিখিত পরিকল্পনা দেয়

  |--Compute Scalar(DEFINE:([Expr1003]=CONVERT_IMPLICIT(int,[Expr1004],0)))
       |--Stream Aggregate(DEFINE:([Expr1004]=Count(*)))
            |--Index Scan(OBJECT:([master].[dbo].[spt_values].[ix2_spt_values_nu_nc]))

এসকিউএল সার্ভার প্রক্রিয়াতে একটি ডিবাগার সংযুক্ত করা এবং নীচে সম্পাদন করার সময় এলোমেলোভাবে বিরতি

DECLARE @V int 

WHILE (1=1)
    SELECT @V=1 WHERE EXISTS (SELECT 1 FROM ##T) OPTION(RECOMPILE)

আমি দেখেছি যে বেশিরভাগ ক্ষেত্রে টেবিলটিতে 1,024 কলাম রয়েছে কল স্ট্যাকটি নীচের মতো কিছু দেখায় যে এটি SELECT 1ব্যবহার করার সময়ও কলাম মেটাডেটা লোড করার সময়টি সত্যই ব্যয় করে চলেছে (ক্ষেত্রে যেখানে টেবিলটিতে 1 টি কলাম এলোমেলোভাবে ভেঙে 10 টি চেষ্টায় কল স্ট্যাকের এই বিটটিকে আঘাত করে না)

sqlservr.exe!CMEDAccess::GetProxyBaseIntnl()  - 0x1e2c79 bytes  
sqlservr.exe!CMEDProxyRelation::GetColumn()  + 0x57 bytes   
sqlservr.exe!CAlgTableMetadata::LoadColumns()  + 0x256 bytes    
sqlservr.exe!CAlgTableMetadata::Bind()  + 0x15c bytes   
sqlservr.exe!CRelOp_Get::BindTree()  + 0x98 bytes   
sqlservr.exe!COptExpr::BindTree()  + 0x58 bytes 
sqlservr.exe!CRelOp_FromList::BindTree()  + 0x5c bytes  
sqlservr.exe!COptExpr::BindTree()  + 0x58 bytes 
sqlservr.exe!CRelOp_QuerySpec::BindTree()  + 0xbe bytes 
sqlservr.exe!COptExpr::BindTree()  + 0x58 bytes 
sqlservr.exe!CScaOp_Exists::BindScalarTree()  + 0x72 bytes  
... Lines omitted ...
msvcr80.dll!_threadstartex(void * ptd=0x0031d888)  Line 326 + 0x5 bytes C
kernel32.dll!_BaseThreadStart@8()  + 0x37 bytes 

এই ম্যানুয়াল প্রোফাইলিংয়ের প্রয়াসটিকে ভিএস 2012 কোড প্রোফাইলার ব্যাক আপ করেছে যা দুটি ক্ষেত্রে সংকলনের সময় গ্রহণকারী ফাংশনগুলির একটি খুব আলাদা নির্বাচন দেখায় ( শীর্ষ 15 ফাংশন 1024 কলাম বনাম শীর্ষ 15 ফাংশন 1 কলাম )।

সংস্করণ SELECT 1এবং SELECT *সংস্করণ উভয়ই কলামের অনুমতিগুলি পরীক্ষা করতে সক্ষম হয় এবং যদি ব্যবহারকারীকে টেবিলের সমস্ত কলামে অ্যাক্সেস না দেওয়া হয় তবে ব্যর্থ হন।

আমি গাদা একটি কথোপকথন থেকে আঁকিয়ে একটি উদাহরণ

CREATE USER blat WITHOUT LOGIN;
GO
CREATE TABLE dbo.T
(
X INT PRIMARY KEY,
Y INT,
Z CHAR(8000)
)
GO

GRANT SELECT ON dbo.T TO blat;
DENY SELECT ON dbo.T(Z) TO blat;
GO
EXECUTE AS USER = 'blat';
GO

SELECT 1
WHERE  EXISTS (SELECT 1
               FROM   T); 
/*  ↑↑↑↑ 
Fails unexpectedly with 

The SELECT permission was denied on the column 'Z' of the 
           object 'T', database 'tempdb', schema 'dbo'.*/

GO
REVERT;
DROP USER blat
DROP TABLE T

সুতরাং কেউ অনুমান করতে পারে যে ব্যবহার করার সময় সামান্য আপাত পার্থক্যটি SELECT some_not_null_colহ'ল এটি নির্দিষ্ট কলামে কেবলমাত্র অনুমতিগুলি পরীক্ষা করে (যদিও এখনও সকলের জন্য মেটাডেটা লোড করে)। তবে অন্তর্নিহিত সারণীতে কলামগুলির সংখ্যা বাড়ার সাথে যদি কিছু ছোট হয় তবে দুটি পদ্ধতির মধ্যে শতাংশের পার্থক্য হিসাবে এটি সত্যের সাথে খাপ খায় না বলে মনে হয়।

কোনও ইভেন্টে আমি তাড়াহুড়া করব না এবং আমার ফর্মটিতে আমার সমস্ত প্রশ্নের পরিবর্তন করব না কারণ পার্থক্যটি খুব সামান্য এবং কোয়েরি সংকলনের সময় কেবল স্পষ্ট। অপসারণ OPTION (RECOMPILE)যাতে পরবর্তী মৃত্যুদন্ড কার্যকর করা ক্যাশেড পরিকল্পনাটি ব্যবহার করতে পারে নীচে দেওয়া।

এখানে চিত্র বর্ণনা লিখুন

+-------------+-----------+------------+-----------+--------------+
| Num of Cols |     *     |     1      |    PK     | Not Null col |
+-------------+-----------+------------+-----------+--------------+
| 2           | 144933.25 | 145292     | 146029.25 | 143973.5     |
| 4           | 146084    | 146633.5   | 146018.75 | 146581.25    |
| 8           | 143145.25 | 144393.25  | 145723.5  | 144790.25    |
| 16          | 145191.75 | 145174     | 144755.5  | 146666.75    |
| 32          | 144624    | 145483.75  | 143531    | 145366.25    |
| 64          | 145459.25 | 146175.75  | 147174.25 | 146622.5     |
| 128         | 145625.75 | 143823.25  | 144132    | 144739.25    |
| 256         | 145380.75 | 147224     | 146203.25 | 147078.75    |
| 512         | 146045    | 145609.25  | 145149.25 | 144335.5     |
| 1024        | 148280    | 148076     | 145593.25 | 146534.75    |
+-------------+-----------+------------+-----------+--------------+
| Total       | 1454769   | 1457884.75 | 1454310   | 1456688.75   |
+-------------+-----------+------------+-----------+--------------+

আমার ব্যবহৃত পরীক্ষার স্ক্রিপ্টটি এখানে পাওয়া যাবে


4
+1 এই উত্তরটি বাস্তব তথ্য পাওয়ার জন্য জড়িত প্রচেষ্টার জন্য আরও বেশি ভোটের দাবিদার ser
জন

4
এসকিউএল সার্ভারের কোন সংস্করণে এই পরিসংখ্যানগুলি উত্পন্ন হয়েছিল তা সম্পর্কে কোনও ধারণা?
মার্টিন ব্রাউন

4
@ মার্টিনব্রাউন - আইআইআরসি মূলত ২০০৮ যদিও আমি সম্প্রতি সাম্প্রতিক সম্পাদনার জন্য ২০১২ সালে পরীক্ষাগুলি পুনরায় পাঠিয়েছি এবং এটির সন্ধান পেয়েছি।
মার্টিন স্মিথ

8

জানার সর্বোত্তম উপায় হ'ল উভয় সংস্করণে দক্ষতা পরীক্ষা করা এবং উভয় সংস্করণের জন্য কার্যকরকরণ পরিকল্পনাটি পরীক্ষা করা। প্রচুর কলাম সহ একটি টেবিল বাছুন।


4
+1 কেন এটিকে নিচে ভোট দেওয়া হয়েছে তা ধারণা নেই। আমি সবসময় ভেবেছিলাম একজন মানুষকে কেবল একটি মাছ দেওয়ার চেয়ে মাছ ধরা শেখানো ভাল। মানুষ কীভাবে কিছু শিখছে?
ওগ্রে গীতসংহিতা 33

5

এসকিউএল সার্ভারে কোনও পার্থক্য নেই এবং এটি এসকিউএল সার্ভারে কখনও সমস্যা হয়নি। অপটিমাইজার জানে যে তারা একই রকম। আপনি যদি মৃত্যুদন্ড কার্যকর করার পরিকল্পনাগুলি দেখে থাকেন তবে দেখতে পাবেন যে সেগুলি অভিন্ন।


1

ব্যক্তিগতভাবে আমি এটিকে খুব, খুব বিশ্বাস করি যে তারা একই ক্যোয়ারী পরিকল্পনায় অনুকূল নয় optim তবে আপনার নির্দিষ্ট পরিস্থিতিতে জানার একমাত্র উপায় এটি পরীক্ষা করা। যদি আপনি করেন, দয়া করে ফিরে রিপোর্ট করুন!


-1

কোনও বাস্তব পার্থক্য নয় তবে একটি খুব ছোট পারফরম্যান্স হিট হতে পারে। থাম্বের নিয়ম হিসাবে আপনার প্রয়োজনের চেয়ে বেশি ডেটা চাইতে হবে না।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.