İki şeyden birinin varlığını test eden bir sorgu sınıfım var. Şeklinde
SELECT CASE
WHEN EXISTS (SELECT 1 FROM ...)
OR EXISTS (SELECT 1 FROM ...)
THEN 1 ELSE 0 END;
Gerçek ifade C'de oluşturulur ve ODBC bağlantısı üzerinden geçici bir sorgu olarak yürütülür.
Son zamanlarda, çoğu durumda ikinci SELECT'in muhtemelen ilk SELECT'ten daha hızlı olacağı ve iki EXISTS deyiminin sırasının değiştirilmesinin, henüz oluşturduğumuz en az bir kötü niyetli test durumunda ciddi bir hızlanmaya neden olduğu ortaya çıktı.
Yapılması gereken şey sadece devam edip iki cümleyi değiştirmektir, ancak SQL Server'ı daha iyi bilen birinin buna ağırlık verip vermeyeceğini görmek istedim. Tesadüf ve bir "uygulama detayı" na güveniyor gibi hissediyorum.
(SQL Server daha akıllı olsaydı, her iki EXISTS yan tümcesini paralel olarak yürütür ve hangisinin ilk kısa devreyi diğerini tamamladığını sağlar.)
Böyle bir sorgunun çalışma süresini sürekli olarak iyileştirmek için SQL Server almanın daha iyi bir yolu var mı?
Güncelleme
Zamanım ve soruma gösterdiğiniz ilgi için teşekkür ederim. Asıl sorgu planları hakkında soru beklemiyordum, ama bunları paylaşmak istiyorum.
Bu, SQL Server 2008R2 ve üstünü destekleyen bir yazılım bileşeni içindir. Verilerin şekli, yapılandırmaya ve kullanıma bağlı olarak oldukça farklı olabilir. İş arkadaşım sorguda bu değişikliği yapmayı düşündü çünkü (örnekte) dbf_1162761$z$rv$1257927703tablo her zaman tablodaki satır sayısından daha fazla veya eşit olacaktır dbf_1162761$z$dd$1257927703- bazen önemli ölçüde daha fazla (büyüklük sıraları).
İşte bahsettiğim küfürlü dava. İlk sorgu yavaş olanıdır ve yaklaşık 20 saniye sürer. İkinci sorgu bir anda tamamlanır.
Değeri ne olursa olsun, yakın zamanda "BİLİNMEYEN OPTİMİZE ET" biti de eklendi çünkü parametre koklaması bazı durumları çöpe atıyordu.
Orijinal sorgu:
SELECT CASE
WHEN EXISTS (SELECT 1 FROM zumero.dbf_1162761$z$rv$1257927703 rv INNER JOIN zumero.dbf_1162761$t$tx tx ON tx.txid=rv.txid WHERE tx.generation BETWEEN 1500 AND 2502)
OR EXISTS (SELECT 1 FROM zumero.dbf_1162761$z$dd$1257927703 dd INNER JOIN zumero.dbf_1162761$t$tx tx ON tx.txid=dd.txid WHERE tx.generation BETWEEN 1500 AND 2502)
THEN 1 ELSE 0 END
OPTION (OPTIMIZE FOR UNKNOWN)
Asıl plan:
|--Compute Scalar(DEFINE:([Expr1006]=CASE WHEN [Expr1007] THEN (1) ELSE (0) END))
|--Nested Loops(Left Semi Join, DEFINE:([Expr1007] = [PROBE VALUE]))
|--Constant Scan
|--Concatenation
|--Nested Loops(Inner Join, WHERE:([scale].[zumero].[dbf_1162761$z$rv$1257927703].[txid] as [rv].[txid]=[scale].[zumero].[dbf_1162761$t$tx].[txid] as [tx].[txid]))
| |--Clustered Index Scan(OBJECT:([scale].[zumero].[dbf_1162761$z$rv$1257927703].[PK__dbf_1162__97770A2F62EEAE79] AS [rv]), WHERE:([scale].[zumero].[dbf_1162761$z$rv$1257927703].[txid] as [rv].[txid]>(0)))
| |--Index Seek(OBJECT:([scale].[zumero].[dbf_1162761$t$tx].[gendex] AS [tx]), SEEK:([tx].[generation] >= (1500) AND [tx].[generation] <= (2502)) ORDERED FORWARD)
|--Nested Loops(Inner Join, OUTER REFERENCES:([tx].[txid]))
|--Clustered Index Scan(OBJECT:([scale].[zumero].[dbf_1162761$t$tx].[PK__dbf_1162__E3BA953EC2197789] AS [tx]), WHERE:([scale].[zumero].[dbf_1162761$t$tx].[generation] as [tx].[generation]>=(1500) AND [scale].[zumero].[dbf_1162761$t$tx].[generation] as [tx].[generation]<=(2502)) ORDERED FORWARD)
|--Index Seek(OBJECT:([scale].[zumero].[dbf_1162761$z$dd$1257927703].[n$dbf_1162761$z$dd$txid$1257927703] AS [dd]), SEEK:([dd].[txid]=[scale].[zumero].[dbf_1162761$t$tx].[txid] as [tx].[txid]), WHERE:([scale].[zumero].[dbf_1162761$z$dd$1257927703].[txid] as [dd].[txid]>(0)) ORDERED FORWARD)
Sabit sorgu:
SELECT CASE
WHEN EXISTS (SELECT 1 FROM zumero.dbf_1162761$z$dd$1257927703 dd INNER JOIN zumero.dbf_1162761$t$tx tx ON tx.txid=dd.txid WHERE tx.generation BETWEEN 1500 AND 2502)
OR EXISTS (SELECT 1 FROM zumero.dbf_1162761$z$rv$1257927703 rv INNER JOIN zumero.dbf_1162761$t$tx tx ON tx.txid=rv.txid WHERE tx.generation BETWEEN 1500 AND 2502)
THEN 1 ELSE 0 END
OPTION (OPTIMIZE FOR UNKNOWN)
Sabit plan:
|--Compute Scalar(DEFINE:([Expr1006]=CASE WHEN [Expr1007] THEN (1) ELSE (0) END))
|--Nested Loops(Left Semi Join, DEFINE:([Expr1007] = [PROBE VALUE]))
|--Constant Scan
|--Concatenation
|--Nested Loops(Inner Join, OUTER REFERENCES:([tx].[txid]))
| |--Clustered Index Scan(OBJECT:([scale].[zumero].[dbf_1162761$t$tx].[PK__dbf_1162__E3BA953EC2197789] AS [tx]), WHERE:([scale].[zumero].[dbf_1162761$t$tx].[generation] as [tx].[generation]>=(1500) AND [scale].[zumero].[dbf_1162761$t$tx].[generation] as [tx].[generation]<=(2502)) ORDERED FORWARD)
| |--Index Seek(OBJECT:([scale].[zumero].[dbf_1162761$z$dd$1257927703].[n$dbf_1162761$z$dd$txid$1257927703] AS [dd]), SEEK:([dd].[txid]=[scale].[zumero].[dbf_1162761$t$tx].[txid] as [tx].[txid]), WHERE:([scale].[zumero].[dbf_1162761$z$dd$1257927703].[txid] as [dd].[txid]>(0)) ORDERED FORWARD)
|--Nested Loops(Inner Join, WHERE:([scale].[zumero].[dbf_1162761$z$rv$1257927703].[txid] as [rv].[txid]=[scale].[zumero].[dbf_1162761$t$tx].[txid] as [tx].[txid]))
|--Clustered Index Scan(OBJECT:([scale].[zumero].[dbf_1162761$z$rv$1257927703].[PK__dbf_1162__97770A2F62EEAE79] AS [rv]), WHERE:([scale].[zumero].[dbf_1162761$z$rv$1257927703].[txid] as [rv].[txid]>(0)))
|--Index Seek(OBJECT:([scale].[zumero].[dbf_1162761$t$tx].[gendex] AS [tx]), SEEK:([tx].[generation] >= (1500) AND [tx].[generation] <= (2502)) ORDERED FORWARD)

