SORU
20 EKİM 2009, Salı


Alt sorgu kullanarak 1 Var ya *Var

Benim bu gibi çekler VAR yazardım:

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

Önceki hayatında DBA biri EXISTS bir fıkra yaptığımda, SELECT * yerine SELECT 1 kullanımı olduğunu söyledi

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

Bu gerçekten bir fark yaratır mı?

CEVAP
26 Mayıs 2011, PERŞEMBE


Bu yanlış anlaşılma nedeni muhtemelen tüm yazılarını sona erecek olan inancı yüzünden. Kolay bir durum değil.

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'

Plan verir

Plan

Bu SQL Server dar Endeksi Endeksi tüm sütunları içermez rağmen sonucu kontrol etmek için kullanılabilir kullanmak mümkün olduğunu gösterir. Dizin erişim operatör beklenen bir gelişme olarak ilk satırı olarak taramayı Durdur anlamına gelen bir yarı döndürülür altındadır.

Yukarıdaki inancın yanlış olduğunu belirtti.

Sorgu Geliştirici ekibinden ancak Conor Cunningham o genellikle küçük bir performans fark yaratabilir, SELECT 1 bu durumda kullanan here açıklarderlemesorgu.

Bu QP ve *'In al genişleyecektir boru hattı ve birbirine bağlayacak erken nesne (bu durumda, listesi sütunlar). O zaman kaldıracaktır gereksiz sütunları doğası gereği sorgu.

Bu kadar basit EXISTS gibi bir sorgu bu:

SELECT col1 FROM MyTable WHERE EXISTS (SELECT * FROM Table2 WHERE MyTable.col1=Table2.col2) * olacak potansiyel olarak büyük genişletilmiş o zaman ne olur, sütun listesi ve bu anlamı tespit EXISTS o herhangi bir gerektirmez sütunlar, temelde hepsi olabilir yani kaldırılacak.

"SELECT 1" zorunda kalmamak gereksiz bunun için meta verileri incelemek sorgu derleme sırasında bir tablo.

Ancak, iki formları zamanında sorgu aynı olması; aynı çalışma zamanları var.

Sütunlar çeşitli numaralar ile boş bir tablo bu sorgu ifade dört olası yolları denedim. SELECT 1 vs SELECT * vs SELECT Primary_Key vs SELECT Other_Not_Null_Column.

Bir döngü OPTION (RECOMPILE) kullanarak sorgular koştum ve saniyede infaz ortalama sayısı ölçülür. Sonuçlar aşağıda

enter image description here

 ------------- ---------- --------- --------- -------------- 
| 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        |
 ------------- ---------- --------- --------- -------------- 

Görüldüğü gibi SELECT 1 SELECT * arasında tutarlı kazanan yok ve iki yaklaşım arasındaki fark önemsİzdİr. SELECT Not Null col SELECT PK biraz daha hızlı olsa görünür.

Sorgular, dört tablodaki sütun sayısı arttıkça performansı düşürebilir.

Tablo boş olduğu için bu ilişki sütun meta veri miktarı sadece o kadar karmaşık görünüyor. COUNT(1) kolay bu süreci bir noktada COUNT(*) * altına yazılmış olur.

SET SHOWPLAN_TEXT ON;

GO

SELECT COUNT(1)
FROM master..spt_values

Aşağıdaki plan verir

  |--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]))

SQL Sunucu işlemi bir hata ayıklayıcı ekleme ve rastgele iken kırma altında yürütülüyor

DECLARE @V int 

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

Bulduğum durumlarda nerede masa 1024 sütun çoğu zaman çağrı yığını gibi bir şey gibi aşağıda gösteren bu harcama gerçekten büyük bir bölümünün yükleme süresini sütun meta verileri bile SELECT 1 kullanılır (durum nereye Tablo 1 sütun rasgele kırma dövmedim biraz da çağrı yığını içinde 10 deneme)

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 

Bu manuel profil oluşturma girişimi işlevleri iki dava için derleme zaman alıcı çok farklı bir seçim gösteren VS 2012 kod profiler (Top 15 Functions 1024 columns vs Top 15 Functions 1 column) tarafından da desteklenmektedir.

Her iki SELECT 1 SELECT * sürümleri kontrol sütun izinleri rüzgar ve kullanıcı tablodaki tüm sütunlar için erişim izni ise başarısız.

Bir sohbette ben cribbed bir örnek the heap

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

Bir SELECT some_not_null_col kullanarak sadece belirli bir sütun (gerçi hala meta yükler) izinlerini kontrol rüzgarlar o zaman küçük görünen bu fark, spekülasyon olabilir. Ancak bu olursa alttaki tablo artar sütun sayısı olarak daha küçük olursa, iki yaklaşım arasındaki yüzde fark olarak gerçekleri ile pek uymuyor.

Her halükarda dışarı fırlarken ve fark çok küçük ve sorgu derleme sırasında sadece çok açık olduğundan bu forma tüm sorgular değişen olmayacağım. Sonraki çalıştırma önbelleğe alınmış bir plan kullanabilmesi OPTION (RECOMPILE) kaldırma aşağıdaki verdi.

enter image description here

 ------------- ----------- ------------ ----------- -------------- 
| 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   |
 ------------- ----------- ------------ ----------- -------------- 

The test script I used can be found here

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • EmbarkToHeaven

    EmbarkToHeav

    3 EYLÜL 2007
  • graham025

    graham025

    25 NİSAN 2006
  • o0oCyrusViruso0o

    o0oCyrusViru

    11 Mart 2008