UNIONing iki sonuç kümesi neden ORIN yan tümcesinde OR kullanarak daha iyi olabilir göstermek için bir örnek sorgu planı üretmeye çalışıyorum. Yazdığım bir sorgu planı beni çok üzdü. Users.Reputation üzerinde kümelenmemiş bir dizin ile StackOverflow veritabanı kullanıyorum.
CREATE NONCLUSTERED INDEX IX_NC_REPUTATION ON dbo.USERS(Reputation)
SELECT DISTINCT Users.Id
FROM dbo.Users
INNER JOIN dbo.Posts
ON Users.Id = Posts.OwnerUserId
OR Users.Id = Posts.LastEditorUserId
WHERE Users.Reputation = 5
Sorgu planı https://www.brentozar.com/pastetheplan/?id=BkpZU1MZE adresinde , benim için sorgu süresi 4:37 dk, 26612 satır döndürüldü.
Daha önce var olan bir tablodan bu sürekli tarama stilinin yaratıldığını görmedim - her kullanıcı için neden sürekli bir tarama yapıldığını bilmiyorum, sürekli bir tarama genellikle kullanıcı tarafından girilen tek bir satır için kullanıldığında örneğin SELECT GETDATE (). Neden burada kullanılıyor? Gerçekten bu sorgu planı okuma bazı rehberlik takdir ediyorum.
Bunu VEYA bir BİRLİĞE böldüğümde, aynı 26612 satır döndürülmüş olarak 12 saniyede çalışan standart bir plan oluşturur.
SELECT Users.Id
FROM dbo.Users
INNER JOIN dbo.Posts
ON Users.Id = Posts.OwnerUserId
WHERE Users.Reputation = 5
UNION
SELECT Users.Id
FROM dbo.Users
INNER JOIN dbo.Posts
ON Users.Id = Posts.LastEditorUserId
WHERE Users.Reputation = 5
Bu planı şu şekilde yorumluyorum:
- Yayınlardan 41782500 satırın tümünü alın (gerçek satır sayısı, Yayınlardaki CI taramasıyla eşleşir)
- Yayınlardaki her 41782500 satır için:
- Skaler üretin:
- Expr1005: OwnerUserId
- Expr1006: OwnerUserId
- Expr1004: Statik değer 62
- Expr1008: LastEditorUserId
- Expr1009: LastEditorUserId
- Expr1007: Statik değer 62
- Birleştirmede:
- Exp1010: Expr1005 (OwnerUserId) null değilse, Expr1008 (LastEditorUserID) kullanan başka bir şey kullanın
- Expr1011: Expr1006 (OwnerUserId) boş değilse bunu kullanın, aksi takdirde Expr1009 (LastEditorUserId) kullanın
- Expr1012: Expr1004 (62) boşsa, başka Expr1007 (62) kullanın
- Hesaplama skalerinde: Bir ve işaretinin ne yaptığını bilmiyorum.
- Expr1013: 4 [ve?] 62 (Expr1012) = 4 ve OwnerUserId IS NULL (NULL = Expr1010)
- Expr1014: 4 [ve?] 62 (Expr1012)
- Expr1015: 16 ve 62 (Expr1012)
- Siparişe Göre Sırala:
- Expr1013 Desc
- Expr1014 Artan
- Expr1010 Artan
- Deneyim1015
- Birleştirme Aralığı'nda Expr1013 ve Expr1015'i kaldırdı (bunlar girişlerdir, ancak çıkış değildir)
- İçine yerleştirilmiş döngülerin altındaki Dizin aramasında, arama tahminleri olarak Expr1010 ve Expr1011 kullanıyor, ancak IX_NC_REPUTATION 'dan Expr1010 ve Expr1011 içeren alt ağaca iç içe döngü birleştirme yapmadığında bunlara nasıl erişebileceğini anlamıyorum. .
- İç İçe Döngüler birleşimi yalnızca önceki alt ağaçta eşleşmesi olan Users.ID'lerini döndürür. Yüklemeli itme nedeniyle, IX_NC_REPUTATION üzerindeki dizin aramasından döndürülen tüm satırlar döndürülür.
- Son İç İçe Döngüler birleştirilir: Her bir Yayın kaydı için, aşağıdaki veri kümesinde bir eşleşmenin bulunduğu Users.Id çıktısını alın.
SELECT Users.Id FROM dbo.Users WHERE Users.Reputation = 5 AND EXISTS (SELECT 1 FROM dbo.Posts WHERE Users.Id IN (Posts.OwnerUserId, Posts.LastEditorUserId) ) ;
SELECT Users.Id FROM dbo.Users WHERE Users.Reputation = 5 AND ( EXISTS (SELECT 1 FROM dbo.Posts WHERE Users.Id = Posts.OwnerUserId) OR EXISTS (SELECT 1 FROM dbo.Posts WHERE Users.Id = Posts.LastEditorUserId) ) ;