LIKE endeksi kullanıyor, CHARINDEX kullanmıyor mu?


22

Bu soru eski sorumla ilgili . Aşağıdaki sorgu yürütmek için 10 ila 15 saniye sürüyordu:

SELECT [customer].[Customer name],[customer].[Sl_No],[customer].[Id]
FROM [company].dbo.[customer]
WHERE (Charindex('123456789',CAST([company].dbo.[customer].[Phone no] AS VARCHAR(MAX)))>0) 

Bazı makalelerde endekslemenin kullanıldığını CASTve CHARINDEXfaydalanmayacağını gördüm . Kullanırken LIKE '%abc%'indekslemeden yararlanmayacağını söyleyen bazı makaleler de var LIKE 'abc%':

http://bytes.com/topic/sql-server/answers/81467-using-charindex-vs-like-where /programming/803783/sql-server-index-any-improvement-for benzeri sorgular http://www.sqlservercentral.com/Forums/Topic186262-8-1.aspx#bm186568

Benim durumumda sorguyu şu şekilde yeniden yazabilirim:

SELECT [customer].[Customer name],[customer].[Sl_No],[customer].[Id]
FROM [company].dbo.[customer]
WHERE [company].dbo.[customer].[Phone no]  LIKE '%123456789%'

Bu sorgu öncekiyle aynı çıktıyı verir. Sütun için kümelenmemiş bir dizin oluşturdum Phone no. Bu sorguyu çalıştırdığımda sadece 1 saniyede çalışıyor . Bu daha önce 14 saniye ile karşılaştırıldığında büyük bir değişiklik .

LIKE '%123456789%'İndekslemeden nasıl yararlanır?

Listelenen makaleler neden performansı artırmayacağını belirtiyor?

Kullanılacak sorguyu yeniden yazmaya çalıştım CHARINDEX, ancak performans hala yavaş. Neden sorgu CHARINDEXgöründüğü gibi indekslemeden faydalanmıyor LIKE?

Kullanarak sorgula CHARINDEX:

SELECT [customer].[Customer name],[customer].[Sl_No],[customer].[Id]
 FROM [Company].dbo.[customer]
 WHERE ( Charindex('9000413237',[Company].dbo.[customer].[Phone no])>0 ) 

Yürütme planı:

görüntü tanımını buraya girin

Kullanarak sorgula LIKE:

SELECT [customer].[Customer name],[customer].[Sl_No],[customer].[Id]
 FROM [Company].dbo.[customer]
 WHERE[Company].dbo.[customer].[Phone no] LIKE '%9000413237%'

Yürütme planı:

LIKE sorgu planı

Yanıtlar:


28

LIKE '% 123456789%' dizine eklemekten nasıl yarar sağlar?

Sadece birazcık. Sorgu işlemcisi , tüm tablo yerine eşleşmeleri arayan kümelenmemiş dizini tarayabilir (kümelenmiş dizin). Kümelenmemiş dizinler genellikle oluşturuldukları tablodan daha küçüktür, bu nedenle kümelenmemiş dizini taramak daha hızlı olabilir.

Olumsuz tarafı, sorgunun kümelenmemiş dizin tanımına dahil edilmeyen tüm sütunların, satır başına taban tablosunda aranması gerektiğidir.

Doktor, tabloyu taramak (kümelenmiş dizin) ve kümelenmemiş dizini maliyet tahminlerine göre aramalarla taramak arasında bir karar verir. Tahmini maliyetler, optimize edicinin sizin seçmenizi veya öngörmeyi ne kadar beklediğine büyük ölçüde bağlıdır .LIKECHARINDEX

Listelenen makaleler neden performansı artırmayacağını belirtiyor?

Bir İçin LIKEgelmez koşul değil , bir joker ile başlar, SQL Server gerçekleştirebilirsiniz kısmi tarama şeyi tarayarak yerine indeksi. Örneğin, LIKE 'A%yalnızca dizin kayıtlarını >= 'A've < 'B'(kesin sınır değerleri harmanlamaya bağlıdır) test edilerek doğru bir şekilde değerlendirilebilir .

Bu tür sorgu b-ağacı dizinlerinin aranma yeteneğini kullanabilir: ilk önce >= 'A'b-ağacı kullanarak ilk kayda gidebiliriz , sonra < 'B'testi geçemeyen bir kayda ulaşıncaya kadar indeks tuşu sırayla ileriye doğru tarayabiliriz . LIKETesti yalnızca daha az sayıda satıra uygulamamız gerektiğinden , performans genellikle daha iyidir.

Buna karşılık, LIKE '%Akısmi bir taramaya dönüştürülemez, çünkü nereden başlayacağınızı veya sonlayacağımızı bilmiyoruz; herhangi bir kayıt sona erebilir 'A', bu nedenle tüm dizini taramayı ve her satırı ayrı ayrı test etmeyi geliştiremeyiz.

Kullanılacak sorguyu yeniden yazmaya çalıştım CHARINDEX, ancak performans hala yavaş. CHARINDEXLIKE sorgusu göründüğü gibi neden indekslemeden faydalanmıyor?

Sorgu en iyi duruma getiricisi, her iki durumda da tablo tarama (kümelenmiş dizin) ve kümelenmemiş dizini tarama (taramalarla) arasında aynı seçeneğe sahiptir .

Seçim, maliyet tahminine göre ikisi arasında yapılır . Öyle olur ki, SQL Server bu iki yöntem için farklı bir tahmin üretebilir. İçin LIKEsorgu şeklinde, tahmin makul doğru tahmin üretmek için özel dize istatistiklerini kullanmak mümkün olabilir. CHARINDEX > 0Formu tahminine dayanarak, bir tahmin üretir.

Farklı tahminler, optimize edicinin, Kümelenmiş Dizin Taraması CHARINDEXve Kümelenmemiş Dizin Taraması için Aramaları seçmesini sağlamak için yeterlidir LIKE. CHARINDEXSorguyu kümelenmemiş dizini bir ipucu ile kullanmaya zorlarsanız, aynı plana sahip LIKEolacaksınız ve performans yaklaşık olarak aynı olacaktır:

SELECT
    [Customer name],
    [Sl_No],
    [Id]
FROM dbo.customer WITH (INDEX (f))
WHERE 
    CHARINDEX('9000413237', [Phone no]) >0;

Çalışma zamanında işlenen satır sayısı her iki yöntem için de aynı olacaktır; LIKEbu durumda form bu durumda daha doğru bir tahmin oluşturur, bu nedenle sorgu iyileştirici daha iyi bir plan seçer.

LIKE %thing%Sık sık aramaya ihtiyacınız olduğunu fark ederseniz , SQL Server'da Trigram Wildcard String Search'te yazdığım bir tekniği düşünebilirsiniz .


16

SQL Server şeklinde dize sütunlardaki altdizgelerin istatistiklerini tutan denemeden tarafından kullanılabilen LIKEsorguya ama vermeyerek CHARINDEX.

Bkz Dize Özeti İstatistik Bu konuda daha fazla için bölüm.

Birkaç önemli uyarı, herhangi bir joker karakterin ESCAPEanahtar kelimeden ziyade köşeli parantez tekniğiyle yapılması ve 80 karakterden daha uzun olan karakter dizileri için yalnızca ilk ve son 40 karakterin kullanılması gerektiğidir.

WHERE ( Charindex('9000413237',[Company].dbo.[customer].[Phone no])>0 ) 

Standart eşitsizliği sadece satırların% 30'unun iade edileceğini öngörmek için kullanacaktır.

LIKE(Sizin durumunuzda) sorgu muhtemelen çok daha az satır yüklemi maç olacak tahmin ediyor.

Önde gelen joker karakterin dizin aramasını engellediğini unutmayın. Dizinin tamamı hala taranıyor, ancak kümelenmiş dizinden daha dar olanı kullanıyor. Daha dar olan dizin, sorgu tarafından kullanılan tüm sütunları kapsamaz; bu nedenle, ikinci plan, eksik sütunları almak için bir anahtar araması gerektirir.

Bu planın% 30 tahminiyle seçilmesi son derece düşük bir ihtimal. SQL Server, kümelenmiş dizinin tamamını taramanın ve daha fazla arama yapılmasını önlemenin daha ucuz olacağını düşünecektir. Ek örnekler için devrilme noktasındaki bu makaleye bakın .


açıklamanla ilgili net değilim. Benzeri kullanmanın charindex'ten daha iyi olduğunu mu söylüyorsunuz?
BT araştırmacısı

3
@ITresearcher - Evet, potansiyel olarak, sadece bir battaniye kullanmak yerine, koşulu ( 30%) kaç tane satırın eşleştireceğini tahmin etmek ( ) LIKEverilen kalıba ve dizi özet istatistiklerine bakabilir ve daha doğru bir tahmin türetebilir. Bununla silahlı, farklı ve daha uygun bir plan seçebilir.
Martin Smith,

3
... ya da "en kötü durumda" aynı plan.
Aaron Bertrand
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.