SQL deyimini anlaşılır yapan nedir?


253

Tanım gereği (en azından gördüklerimden) sargable, bir sorgunun, sorgu motorunun, sorgunun kullandığı yürütme planını optimize etmesini sağlayabileceği anlamına gelir. Cevapları aramaya çalıştım, ama bu konuda fazla bir şey yok gibi görünüyor. Yani soru şu, bir SQL sorgusunu anlaşılabilir kılan nedir veya yapmaz? Herhangi bir belge çok takdir edilecektir.

Referans için: SARGable


58
"Sargable" için +1. Bugünkü sözüm bu. :-p
BFree

1
Adam'ın cevabına, bilgi dağlarının çoğu durumda her DB motoruna son derece özel olduğunu da ekleyebilirim.
Hoagie

31
SARG = ARGument'i Ara. Komik olan şey: "SARG" Almanca "Tabut" anlamına gelir, bu yüzden insanlar SARGABLE hakkında konuştuğunda her zaman gülümsemeliyim - bir tabuta konabilir mi? :-)
marc_s

hırsızlık ortamınıza bağlıdır. MySQL'ler
Frank Farmer

"Arama tabloları" yerine serbest metin alanlarına sahip olmak da sorguyu sersemletme ruhuna aykırıdır. Kullanıcılar, serbest metin (ör. Şehir adı) girerken bir şeyleri yanlış yazarken, arama tabloları kullanıcıları doğru yazılmış bir giriş seçmeye zorlar. Hafif ekstra bela iyi değer, çünkü bu yüklemde '% ...%' LIKE yerine düzgün bir şekilde endekslenebilir.
Ters Mühendis

Yanıtlar:


256

Sorguyu anlaşılmaz hale getirecek en yaygın şey , nereye yan tümcesinde bir işlevin içine bir alan eklemektir :

SELECT ... FROM ...
WHERE Year(myDate) = 2008

SQL optimizer, mevcut olsa bile myDate'de bir dizin kullanamaz. Kelimenin tam anlamıyla tablonun her satırı için bu işlevi değerlendirmek zorunda kalacak. Kullanmak çok daha iyi:

WHERE myDate >= '01-01-2008' AND myDate < '01-01-2009'

Diğer bazı örnekler:

Bad: Select ... WHERE isNull(FullName,'Ed Jones') = 'Ed Jones'
Fixed: Select ... WHERE ((FullName = 'Ed Jones') OR (FullName IS NULL))

Bad: Select ... WHERE SUBSTRING(DealerName,4) = 'Ford'
Fixed: Select ... WHERE DealerName Like 'Ford%'

Bad: Select ... WHERE DateDiff(mm,OrderDate,GetDate()) >= 30
Fixed: Select ... WHERE OrderDate < DateAdd(mm,-30,GetDate()) 

7
GROUP BYSorgunun içine bir işlev eklemek, sorgunun anlaşılmaz olmasına neden olur mu?
Mike Bailey

1
Bazı veritabanı motorları (Oracle, PostgreSQL) ifadelerde dizinleri destekler, bilmiyor musunuz?
Craig

3
Daha da iyi bir versiyonu WHERE ((FullName = 'Ed Jones') OR (FullName IS NULL))olabilir SELECT... FROM ... WHERE FullName = 'Ed Jones' UNION SELECT...FROM...WHERE FullName IS NULLmi? Bir zamanlar bir optimizasyon adam tarafından OR nerede kullanarak yan tümce sorguları çözebilir söylendi ..?
Yüksek Ovalar Grifter

2
Bu sorguda bir BİRLİK TÜMÜ kullanmanız gerektiğinde - birliğin örtülü bir ayrımı vardır, bu da sorguyu karşılıklı olarak özel veri kümelerine ihtiyaç duyduğunuzda olması gerekenden çok daha pahalı hale getirir
Devin Lamothe

1
@BradC MSSQL 2016'da Select ... WHERE isNull(FullName,'Ed Jones') = 'Ed Jones've arasında yürütme planı farkı yoktur Select ... WHERE ((FullName = 'Ed Jones') OR (FullName IS NULL)). İkisi de FullName üzerindeki dizini kullanır ve bir dizin araması yapar.
CEGRD

79

Bunu yapma:

WHERE Field LIKE '%blah%'

Bu bir tablo / dizin taramasına neden olur, çünkü LIKE değeri bir joker karakterle başlar.

Bunu yapma:

WHERE FUNCTION(Field) = 'BLAH'

Bu tablo / dizin taramasına neden olur.

Veritabanı sunucusu FUNCTION () yöntemini tablodaki her satıra göre değerlendirmeli ve ardından 'BLAH' ile karşılaştırmalıdır.

Mümkünse, tersini yapın:

WHERE Field = INVERSE_FUNCTION('BLAH')

Bu, INVERSE_FUNCTION () parametresini bir kez çalıştırır ve yine de dizinin kullanılmasına izin verir.


5
Fonksiyonu çevirmeyle ilgili öneriniz gerçekten sadece fonksiyon veriyi döndürdüğünde işe yarar (yani f (f (n)) = n).
Adam Robinson

5
Doğru. INVERSE_FUNCTION eklemeyi düşündüm ama kafa karıştırıcı olmak istemedim. Ben değiştireceğim.
plaj

9

Bu cevapta veritabanının yeterli örtme indeksine sahip olduğunu varsayıyorum. Bu konu hakkında yeterli soru var .

Çoğu zaman, bir sorgunun yatkınlığı, ilgili endekslerin devrilme noktası ile belirlenir. Devrilme noktası, bir tabloyu veya sonuç kümesini diğerine birleştirirken dizin arama ve tarama arasındaki farkı tanımlar. Bir arayış elbette tüm bir tabloyu taramaktan çok daha hızlıdır, ancak çok sayıda satır aramanız gerektiğinde, tarama daha anlamlı olabilir.

Diğer şeylerin yanı sıra, optimize edici bir tablonun sonuç satırlarının bir sonraki tabloda olası bir dizinin devrilme noktasından daha az olmasını beklediğinde, SQL ifadesi daha anlaşılır olur.

Burada ayrıntılı bir gönderi ve örnek bulabilirsiniz .


4

Bir operasyonun anlaşılabilir sayılması için, sadece mevcut bir endeksi kullanabilmesi yeterli değildir. Yukarıdaki örnekte, burada yan tümcesinde dizinlenmiş bir sütuna işlev çağrısı eklenmesi, büyük olasılıkla tanımlanan dizinden bir miktar avantaj sağlayacaktır. "Tarama" aka o sütundaki (indeks) tüm değerleri alır ve daha sonra sağlanan filtre değeri ile uyuşmayan değerleri ortadan kaldırır. Çok sayıda satıra sahip tablolar için hala yeterince verimli değildir. Saptırılabilirliği gerçekten tanımlayan şey, sıralanan öğeler dizisi için yarı-set eliminasyona dayanan ikili arama yöntemini kullanarak b-ağacı dizinini çaprazlama yeteneğidir. SQL'de, yürütme planında "dizin arama" olarak görüntülenir.

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.