53 milyon okumaya neden olan sp_cursorprepexec?


9

SQL Server 2012 ile bir Dynamics AX 2012 yüklemesi yapıyoruz. İmleçlerin artık kullanılmaması gerektiğini biliyorum, ancak AX bunu kullanıyor ve bu davranışı değiştiremeyiz, bu yüzden onunla çalışmak zorundayız.

Bugün 53 milyondan fazla okuma ve 20 dakikadan fazla yürütme süresi ile çok kötü bir sorgu yakaladım.

Bu sorguyu SentryOne izleme aracımızla yakaladım.

declare @p1 int
set @p1=1073773227
declare @p2 int
set @p2=180158805
declare @p5 int
set @p5=16
declare @p6 int
set @p6=1
declare @p7 int
set @p7=2
exec sp_cursorprepexec @p1 output,@p2 output,N'@P1 bigint,@P2 nvarchar(5),@P3 bigint,@P4 nvarchar(8),@P5 bigint,@P6 bigint,@P7 bigint,@P8 bigint,@P9 bigint,@P10 bigint,@P11 bigint,@P12 bigint,@P13 bigint,@P14 bigint,@P15 bigint,@P16 bigint,@P17 bigint,@P18 bigint,@P19 nvarchar(5),@P20 bigint,@P21 bigint,@P22 bigint,@P23 bigint,@P24 bigint',N'SELECT T1.PRODUCT,T1.EXTERNALVENDPARTY,T1.LIFECYCLESTATUS,T1.RECID,T2.ECORESPRODUCT,T2.ECORESDISTINCTPRODUCTVARIANT,T2.SGE,T2.ECORESREFORDERNUM,T2.ORDERNUM,T2.RECID,T3.ECORESREFORDERNUM,T3.NAME1,T3.NAME2,T3.NAME3,T3.RECID,T4.ECORESPRODUCT,T4.EXTERNALITEMID,T4.ECORESDISTINCTPRODUCTVARIANT,T4.RECID,T5.RECID,T5.PERSON,T6.RECID,T6.NAME,T6.INSTANCERELATIONTYPE,T7.RECID,T7.NAME,T7.INSTANCERELATIONTYPE,T8.PARTY,T8.ACCOUNTNUM,T8.RECID,T9.RECID,T9.DISPLAYPRODUCTNUMBER,T9.INSTANCERELATIONTYPE,T10.PRODUCT,T10.CATEGORY,T10.RECID,T11.RECID,T11.CODE,T11.NAME,T11.INSTANCERELATIONTYPE FROM INVENTTABLE T1 CROSS JOIN ECORESPRODUCTORDERNUM T2 CROSS JOIN ECORESPRODUCTORDERNUMTRANSLATION T3 LEFT OUTER JOIN VENDEXTERNALITEM T4 ON ((T4.PARTITION=5637144576) AND ((T2.ECORESPRODUCT=T4.ECORESPRODUCT) AND (T4.ECORESDISTINCTPRODUCTVARIANT=@P1))) CROSS JOIN HCMWORKER T5 CROSS JOIN DIRPARTYTABLE T6 CROSS JOIN DIRPARTYTABLE T7 CROSS JOIN VENDTABLE T8 CROSS JOIN ECORESPRODUCT T9 CROSS JOIN ECORESPRODUCTCATEGORY T10 CROSS JOIN ECORESCATEGORY T11 WHERE (((T1.PARTITION=5637144576) AND (T1.DATAAREAID=N''087'')) AND (T1.DATAAREAID=@P2)) AND ((T2.PARTITION=5637144576) AND ((T2.ECORESPRODUCT=T1.PRODUCT) AND (T2.SGE=@P3))) AND ((T3.PARTITION=5637144576) AND ((T3.ECORESREFORDERNUM=T2.ECORESREFORDERNUM) AND (T3.LANGUAGEID=@P4))) AND ((T5.PARTITION=5637144576) AND (T5.RECID=T2.PRODUCTMANAGER)) AND (((T6.PARTITION=5637144576) AND (T6.INSTANCERELATIONTYPE IN (@P5,@P6,@P7,@P8,@P9,@P10,@P11) )) AND (T6.RECID=T5.PERSON)) AND (((T7.PARTITION=5637144576) AND (T7.INSTANCERELATIONTYPE IN (@P12,@P13,@P14,@P15,@P16,@P17,@P18) )) AND (T1.EXTERNALVENDPARTY=T7.RECID)) AND (((T8.PARTITION=5637144576) AND (T8.DATAAREAID=N''087'')) AND ((T7.RECID=T8.PARTY) AND (T8.DATAAREAID=@P19))) AND (((T9.PARTITION=5637144576) AND (T9.INSTANCERELATIONTYPE IN (@P20,@P21,@P22) )) AND (T9.RECID=T1.PRODUCT)) AND ((T10.PARTITION=5637144576) AND (T10.PRODUCT=T9.RECID)) AND (((T11.PARTITION=5637144576) AND (T11.INSTANCERELATIONTYPE IN (@P23,@P24) )) AND (T11.RECID=T10.CATEGORY))',@p5 output,@p6 output,@p7 output,0,N'087',5637146082,N'de',41,2303,2377,2975,2978,5329,6886,41,2303,2377,2975,2978,5329,6886,N'087',3265,3266,3267,2665,4423
select @p1, @p2, @p5, @p6, @p7

Fark ettiğim ilk şey, bu sorgunun bir imleç kullanmasıydı. Merak dışında ifade kopyaladı ve imleç şeyler olmadan Management Studio yürüttüm (Ben çalıştırmak için böylece sorgu için parametreleri yerine itiraf etmeliyim). SSMS içinde sorgu 30 saniye içinde tamamlandı. Çok hızlı değil, ama yine de imleç alternatifinden daha hızlı.

Burada her iki planı da sağlıyorum:

İmleçsiz plan hala çok kötü bir plan ama çok daha iyi. Sorum şu: Birisi bana imleç versiyonunun neden 53 milyon okumaya ihtiyacı olduğunu açıklayabilir mi?

İmleç ile sorgu için istatistikler:

Duration    CPU         Reads       Writes  Est Rows    Actual Rows
1.396.212   1.379.157   53.270.895  3.878   30          2

İmleçsiz sorgu için istatistikler:

Duration    CPU         Reads       Writes  Est Rows    Actual Rows
23.337      1.703       665.113     13      4.287       34.813

2 yerine 34.813 satır almak garip görünüyor; ama doğru parametreleri doldurduğuma eminim. İstatistikleri oradan kopyaladığım için SQL Sentry'den belki de komik bir tuhaflık olduğunu düşündüm.

Umarım sana gerekli tüm bilgileri verebilirim. Ayrıca kimse iyi okumalar varsa daha iyi olurdu imleçler daha iyi anlamak.

Yanıtlar:


10

Her şeyden önce, SQL Sentry'den gelen her iki sorgu için gerçek satır sayısının aşağı yukarı aynı olmaması beni şaşırtıyor.

İkinci. Gerçek bir plan olmadan bir imleçle tahminlerinizin planda ne kadar doğru olduğunu söylemek zor, ancak bazı şeyler bana dikkat çekiyor. (PS: gerçek bir plan almak için buradaki cevabım bölümüne bakın ).

Bununla birlikte, tahmini planınızdan not edilebilecek birkaç şey var.

Parametreleme nedeniyle eşleşmeyen dizinler hakkında bir uyarı var . SQL Server'ın eşleşmeyenleri kullanabilmesi için parametrelerin kaldırılması G / Ç'yi önemli ölçüde artırabilir.

2 plan arasındaki tahmini satır sayısı da önemli ölçüde kapalı. Bir imleçle planınızda, vendexternalitem'den tahmini 11 satırınız vardır. Bir imleç olmadan planınızda, yaklaşık 200K'lık tahmini ve gerçek bir satırınız vardır. 200K kayıtlarınız gerçekten acı verici olabilecek makara operatörüne gidin.

Tüm işleçlerin çılgınca farklı tahminleri vardır (imleç içeren planda çok daha küçüktür), bu nedenle planınız derlenmiş ve imleç olmadan sorguda kullandığınızdan farklı parametre değerleri ile önbelleğe alınmıştır. ( parametre koklaması olarak bilinir )

Ayrıca icat tablosunda index seek + anahtar aramasında çok garip bir seçim var. Plan typeIdx kullanıyor ve sonra kümelenmiş dizine (itemidx) anahtar aramaları yapıyor. Tahminleriniz orada değilse ve SQL Server, IO'yu da açıklayabilecek çok sayıda anahtar arama yapmak zorundaysa. Planınızda bir imleç olmadan sahip olduğunuz stopidx'e aşina değilim ama örtüyor gibi görünüyor, bu yüzden muhtemelen sağladığınız parametreler için daha iyi bir seçim. Ben daha dar çünkü tipidx aldı varsayalım ama bu sorunlu yürütme sağladığınızdan farklı derleme zamanı değerleri nedeniyle olabilir.

Kısacası, bu sorgu için parametreleştirmeyi kaldırırdım, böylece SSMS'deki plan (ve yürütme süreleri) tarafından kanıtlandığı gibi "daha iyi" indeksleri seçerek gerçek değerlerle bir plan oluşturur. Bu, SQL Server'ın filtrelenmiş dizinleri kullanmasına da izin verir. Bunu yapmak için, bir geliştiricinin, bu sorgunun yürütüldüğü uygulama koduna forceliteralsanahtar kelimeyi eklemesini sağlayın ve ne olduğunu görün.

Bu muhtemelen 30 saniye süren bir sorguyu (SSMS'nizdekine benzer) bırakacaktır, ancak bu sadece bir ayarlama meselesidir. Planlarınızda eksik dizin uyarıları var ve ecoresproductordernum.sge ile ilgili bir dizin örneğin yardımcı olabilir ama bu tabloları bilmiyorum ve özelleştirmeler tarafından eklendiğini düşünüyorum. Genel ayar ilkeleri burada yardımcı olacaktır, ancak bu muhtemelen bu cevap için çok geniş olacaktır (dizinleri kapsayan, ...)


Bu benim sorunumu çözdü. Aslında iki problemimiz vardı: Parametre koklaması ve filtre dizileri. Uygulama DirPartyTable için bu garip "in" yan tümcesini üretti AX bazı ilişkileri atladı kaçırdı. Hikayenin sonu: asla masa ilişkilerini atlamayın :)
Hans Vader
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.