Chúng tôi đang chạy cài đặt Dynamics AX 2012 với SQL Server 2012. Tôi biết rằng không nên sử dụng con trỏ nữa nhưng AX đang sử dụng và chúng tôi không thể thay đổi hành vi này vì vậy chúng tôi phải làm việc với nó.
Hôm nay tôi bắt được một truy vấn rất tệ với hơn 53 triệu lượt đọc và thời gian thực hiện lớn hơn 20 phút.
Tôi đã bắt được truy vấn này thông qua công cụ giám sát SentryOne của chúng tôi.
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
Điều đầu tiên tôi nhận thấy là truy vấn này đã sử dụng một con trỏ. Vì tò mò tôi đã sao chép câu lệnh và thực thi nó trong Management Studio mà không có công cụ con trỏ (tôi phải thừa nhận rằng tôi đã thay thế các tham số cho truy vấn để tôi có thể chạy nó). Trong SSMS, truy vấn kết thúc sau 30 giây. Không nhanh lắm, nhưng vẫn nhanh hơn con trỏ thay thế.
Ở đây tôi cung cấp cho bạn cả hai kế hoạch:
- Lập kế hoạch với con trỏ: https://www.brentozar.com/pastetheplan/?id=Sk0aMY-Y-
- Lập kế hoạch không có con trỏ: https://www.brentozar.com/pastetheplan/?id=HJ6ImtWK-
Kế hoạch không có con trỏ vẫn là một kế hoạch rất xấu nhưng tốt hơn nhiều. Câu hỏi của tôi ở đây là: Ai đó có thể vui lòng giải thích cho tôi tại sao phiên bản con trỏ cần 53 triệu lượt đọc không?
Số liệu thống kê cho truy vấn với con trỏ:
Duration CPU Reads Writes Est Rows Actual Rows
1.396.212 1.379.157 53.270.895 3.878 30 2
Số liệu thống kê cho truy vấn không có con trỏ:
Duration CPU Reads Writes Est Rows Actual Rows
23.337 1.703 665.113 13 4.287 34.813
Có vẻ lạ khi lấy 34.813 hàng thay vì 2; nhưng tôi khá chắc chắn rằng tôi đã điền đúng thông số. Tôi nghĩ rằng đây có thể là một trò hề hài hước từ SQL Sentry vì tôi chỉ sao chép số liệu thống kê từ đó.
Tôi hy vọng tôi có thể cung cấp cho bạn tất cả các thông tin cần thiết cho bạn. Ngoài ra nếu bất cứ ai có một số bài đọc tốt, các con trỏ hiểu rõ hơn sẽ là tuyệt vời.