SQL, SQL Alt Sorgularına (Performans) Katılıyor mu?


110

Bunun gibi bir katılma sorgum olup olmadığını bilmek istiyorum -

Select E.Id,E.Name from Employee E join Dept D on E.DeptId=D.Id

ve bunun gibi bir alt sorgu -

Select E.Id,E.Name from Employee Where DeptId in (Select Id from Dept)

Performansı göz önünde bulundurduğumda , iki sorgudan hangisi daha hızlı olur ve neden ?

Ayrıca birini diğerine tercih etmem gereken bir zaman var mı?

Bu çok önemsizse ve daha önce sorduysa özür dilerim ama kafam karıştı. Ayrıca, iki sorgunun performansını ölçmek için kullanmam gereken araçları önerebilirseniz çok iyi olur . Çok teşekkürler!


5
@Lucero, bu soru sql-server-2008 etiketli, burada bahsettiğiniz gönderi MySql etiketli. Cevapların aynı olacağı sonucuna varabilirsiniz. Performans optimizasyonu, iki RDBMS'de farklı şekilde yapılır.
Francois Botha

Yanıtlar:


48

İlk sorgunun daha hızlı olmasını BEKLİYORUM, çünkü temelde bir eşdeğerliğiniz ve açık bir JOIN'iniz var. Benim deneyimime INgöre çok yavaş bir işleçtir, çünkü SQL bunu normalde WHERE"OR" ( WHERE x=Y OR x=Z OR...) ile ayrılmış bir dizi cümle olarak değerlendirir .

TÜM ŞEYLER SQL'de olduğu gibi, kilometreniz değişebilir. Hız, diğer şeylerin yanı sıra büyük ölçüde dizinlere bağlı olacaktır (her iki kimlik sütununda da dizinleriniz var mı? Bu çok yardımcı olacak ...).

% 100 kesinlikle daha hızlı olanı söylemenin tek GERÇEK yolu, performans izlemeyi açmak (IO İstatistikleri özellikle yararlıdır) ve her ikisini de çalıştırmaktır. Çalıştırmalar arasında önbelleğinizi temizlediğinizden emin olun!


16
Bu yanıt hakkında ciddi şüphelerim var, çünkü çoğu DBMS, kesinlikle SQL Server 2008 ve sonrası, tek kimlik alt sorgusunu (ilişkili değil, yani birden fazla dış sorgu sütununa referans vermemek) nispeten hızlı yarı birleştirmeye çeviriyor. Ayrıca, daha önce başka bir cevapta da belirtildiği gibi, ilk gerçek birleştirme, Dept'teki eşleşen kimliğin HER oluşumu için bir satır döndürecektir - bu, benzersiz bir kimlik için hiçbir fark yaratmaz, ancak size başka bir yerde tonlarca kopya verecektir. Bunları DISTINCT veya GROUP BY ile sıralamak başka bir ağır performans yükü olacaktır. SQL Server Management Studio'da yürütme planlarını kontrol edin!
Erik Hart

2
VEYA'ya eşdeğer olan IN yan tümcesi, parametre / değer listelerine uygulanır, ancak çoğunlukla birleştirmeler olarak değerlendirilen alt sorgulara uygulanmaz.
Erik Hart

42

Bunun "Eski ama Altın" bir soru olduğuna inanıyorum. Cevap, duruma bağlı!". Gösteriler o kadar hassas bir konu ki: "Asla alt sorgular kullanmayın, her zaman katılın" demek çok aptalca olur. Aşağıdaki bağlantılarda, çok yararlı bulduğum bazı temel en iyi uygulamaları bulacaksınız:

50000 elementli bir masam var, aradığım sonuç 739 elementti.

İlk başta sorgum şuydu:

SELECT  p.id,
    p.fixedId,
    p.azienda_id,
    p.categoria_id,
    p.linea,
    p.tipo,
    p.nome
FROM prodotto p
WHERE p.azienda_id = 2699 AND p.anno = (
    SELECT MAX(p2.anno) 
    FROM prodotto p2 
    WHERE p2.fixedId = p.fixedId 
)

ve uygulanması 7,9 saniye sürdü.

Sonunda benim sorgum şu:

SELECT  p.id,
    p.fixedId,
    p.azienda_id,
    p.categoria_id,
    p.linea,
    p.tipo,
    p.nome
FROM prodotto p
WHERE p.azienda_id = 2699 AND (p.fixedId, p.anno) IN
(
    SELECT p2.fixedId, MAX(p2.anno)
    FROM prodotto p2
    WHERE p.azienda_id = p2.azienda_id
    GROUP BY p2.fixedId
)

ve 0.0256 saniye sürdü

İyi SQL, güzel.


3
İlginç, GROUP BY eklemenin sorunu nasıl çözdüğünü açıklayabilir misiniz?
cozos

6
Alt sorgu tarafından oluşturulan geçici tablo daha küçüktü. Bu nedenle, kontrol edilecek daha az veri olduğundan yürütme daha hızlıdır.
Sirmyself

2
İlk sorguda dış sorgu ve alt sorgu arasında değişkeni paylaştığınızı düşünüyorum, bu nedenle ana sorgudaki her satır için alt sorgu çalıştırılır, ancak ikincisinde alt sorgu yalnızca bir kez çalışır ve bu şekilde performans artar.
Ali Faradjpour

1
Sql server ve MySql ve ... Sql (NoSql hariç) altyapıda çok benzer. IN (...) yan tümcelerini birleştirmek için (mümkünse) dönüştüren bir tür sorgu optimizasyon motorumuz var. Ancak, iyi indekslenmiş bir sütunda (önem derecesine göre) bir Grubunuz olduğunda, çok daha hızlı olacaktır. Yani gerçekten duruma bağlı.
Alix

10

SQl Sunucusunun bunları nasıl yorumlayacağına ilişkin farklılıkları görmek için yürütme planlarına bakmaya başlayın. Profiler'ı, sorguları birden çok kez çalıştırmak ve farkı elde etmek için de kullanabilirsiniz.

İlişkili alt sorgular kullandığınızda alt sorgular yerine birleştirme kullanımında gerçek, büyük performans kazanımları elde edebileceğiniz bunların korkunç derecede farklı olmasını beklemiyorum.

EXISTS genellikle bu ikisinden birinden daha iyidir ve sol birleştirme tablosunda olmayan tüm kayıtları istediğiniz yerde sol birleşimlerden bahsederken, MEVCUT DEĞİL genellikle çok daha iyi bir seçimdir.


9

Performans, üzerinde yürüttüğünüz veri miktarına bağlıdır ...

20k civarında daha az veri ise. JOIN daha iyi çalışıyor.

Veriler 100k + gibiyse, IN daha iyi çalışır.

Diğer tablodaki verilere ihtiyacınız yoksa, IN iyidir, ancak her zaman EXISTS'e gitmek daha iyidir.

Test ettiğim tüm bu kriterler ve tabloların uygun indeksleri var.


4

Performans aynı olmalıdır; Tablolarınıza doğru dizinlerin ve kümelemenin uygulanması çok daha önemlidir ( bu konuda bazı iyi kaynaklar vardır ).

(Güncellenen soruyu yansıtacak şekilde düzenlendi)


4

İki sorgu anlamsal olarak eşdeğer olmayabilir. Bir çalışan birden fazla departman için çalışıyorsa (çalıştığım kuruluşta mümkün; bu tablonuzun tam olarak normalize edilmediği anlamına gelir), o zaman ilk sorgu yinelenen satırlar döndürürken ikinci sorgu döndürmez. Bu durumda sorguları eşdeğer kılmak için DISTINCTanahtar kelimenin cümleye eklenmesi gerekir ve SELECTbu da performans üzerinde bir etkisi olabilir.

Bir tablonun bir varlığı / sınıfı veya varlıklar / sınıflar arasındaki bir ilişkiyi modellemesi gerektiğini, ancak her ikisini birden modellememesi gerektiğini belirten pratik bir tasarım kuralı vardır. Bu nedenle, OrgChartçalışanlar ve departmanlar arasındaki ilişkiyi modellemek için üçüncü bir tablo oluşturmanızı öneririm .


4

Bunun eski bir gönderi olduğunu biliyorum ama bence bu çok önemli bir konu, özellikle 10 milyondan fazla kayıtlara sahip olduğumuz ve terabaytlarca veriden bahsettiğimiz günümüzde.

Aşağıdaki gözlemlere de ağırlık vereceğim. Tablomda yaklaşık 45 milyon kaydım ([veriler]) ve [kediler] tablomda yaklaşık 300 kaydım var. Bahsetmek üzere olduğum tüm sorgular için kapsamlı indekslemem var.

Örnek 1'i düşünün:

UPDATE d set category = c.categoryname
FROM [data] d
JOIN [cats] c on c.id = d.catid

Örnek 2'ye kıyasla:

UPDATE d set category = (SELECT TOP(1) c.categoryname FROM [cats] c where c.id = d.catid)
FROM [data] d

Örnek 1'in çalışması yaklaşık 23 dakika sürdü. Örnek 2 yaklaşık 5 dakika sürdü.

Dolayısıyla, bu durumda alt sorgunun çok daha hızlı olduğu sonucuna varabilirim. Tabii ki, 1GB / sn'de i / o kapasitesine sahip M.2 SSD sürücüleri kullandığımı (yani baytlar bit değil) kullandığımı unutmayın, bu nedenle indekslerim de gerçekten hızlı. Bu, sizin durumunuzda hızları da etkileyebilir

Bir kereye mahsus bir veri temizliği ise, muhtemelen en iyisi onu çalıştırıp bitirmek. TOP (10000) kullanıyorum ve büyük sorguya ulaşmadan önce ne kadar sürdüğünü görüyorum ve kayıt sayısıyla çarpıyorum.

Üretim veritabanlarını optimize ediyorsanız, verilerin önceden işlenmesini, yani gerçek zamanlı erişimin statik verileri alması için kayıtları eşzamansız olarak güncellemek için tetikleyicileri veya iş komisyoncusu kullanmanızı şiddetle tavsiye ederim.


0

Objektif bir cevap almak için bir Açıklama Planı kullanabilirsiniz.

Sorununuz için, bir Varlık filtresi muhtemelen en hızlısı gerçekleştirecektir.


2
"Bir Varolan filtresi muhtemelen en hızlısı gerçekleştirecektir" - muhtemelen değil, sanırım, kesin bir yanıt gerçek verilere göre test etmeyi gerektirecek olsa da. Mevcut filtrelerin, aynı arama değerlerine sahip birden çok satır olduğu durumlarda daha hızlı olması muhtemeldir; bu nedenle, sorgu aynı departmandan diğer çalışanların kaydedilip kaydedilmediğini kontrol ediyorsa var olan bir filtre daha hızlı çalışabilir, ancak muhtemelen bir departmana bakarken değil tablo.

Son senaryoda daha yavaş çalışır mıydı?
Snekse

İyileştiriciye bağlıydı - belirli koşullar altında olabilir, ancak normalde çok benzer bir performans beklerdim.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.