บังคับให้ SQL Server รันเงื่อนไขการสืบค้นตามที่เขียนไว้หรือไม่


14

ฉันใช้ SQL Server 2008 R2 และฉันมีแบบสอบถามหลอก (SP) นี้:

select ...
from ...
WHERE    @LinkMode IS NULL
     AND (myColumn IN (...very long-running query...))
     ...
     ...

ปัญหาคือว่าแบบสอบถามใช้เวลานานมากในการดำเนินการ - แม้ว่าผมจะดำเนินการ SP @LinkMode=2ด้วย

ดังที่คุณสังเกตเห็นเคียวรีที่รันนานควรถูกเรียกใช้งานต่อเมื่อ @LinkMode เป็นโมฆะซึ่งไม่ใช่กรณีที่นี่ ในกรณีของฉัน @LinkMode = 2!

อย่างไรก็ตามหากฉันเปลี่ยนเป็น:

 select ...
    from ...
    WHERE    1=2
         AND (myColumn IN (...very long time exeted query...))
     ...
     ...

เอสพีไม่ทำงานได้อย่างรวดเร็ว

ฉันเคยได้ยินมาก่อนแล้วว่าบางครั้งเครื่องมือเพิ่มประสิทธิภาพสามารถปรับลำดับของเกณฑ์ให้เหมาะสม

ดังนั้นฉันถาม:

  • แม้ว่าเครื่องมือเพิ่มประสิทธิภาพเลือกเส้นทางที่แตกต่างกันอะไรที่เร็วกว่าการตรวจสอบว่า=null? ผมหมายถึงผมคิดว่าการตรวจสอบว่าif a==nullเป็นมากทำงานได้เร็วกว่าแบบสอบถามยาวอื่น ...

  • ฉันจะบังคับให้ SQL Server เรียกใช้แบบสอบถามตามที่ฉันเขียนไว้ (เรียงตามลำดับเดียวกัน) ได้อย่างไร

คำตอบ:


22

คุณกำลังตกอยู่ใน " จับทั้งหมดแบบสอบถาม " กับดักซึ่งจะมีการอธิบายอย่างดีโดยเกลชอว์นี่

เมื่อต้องการสรุปปัญหา: SQL Server ปรับค่าใช้จ่ายที่สำคัญของการรวบรวมแบบสอบถามให้เหมาะสมโดยการแคชแผนแบบสอบถามหลังจากรวบรวมแล้วตรวจสอบแคชในภายหลังสำหรับแผนการแบบสอบถามที่ตรงกันก่อนการรวบรวมในภายหลัง "การจับคู่" ที่เกิดขึ้นที่นี่เป็นข้อความล้วนดังนั้นค่าจริงของตัวแปรจะไม่ส่งผลกระทบต่อสิ่งนี้

นั่นเป็นสิ่งที่ดี 99% ของเวลา แต่ในบางกรณีก็ไม่ดี กรณีหนึ่งที่ไม่ดีคือเมื่อมีคนพยายามสร้างส่วนคำสั่ง WHERE ราวกับว่ามันเป็นเหมือนคำสั่ง IF ลัดวงจรใน C ฯลฯ ซึ่งใช้งานไม่ได้ดีเพราะคอมไพเลอร์ SQL ต้องทำแผนแบบสอบถามหนึ่งแผนซึ่งจะทำงานโดยไม่คำนึงถึง ของค่าพารามิเตอร์จริง ๆ และวิธีเดียวที่จะสามารถจัดการกับเงื่อนไขการสลับตรรกะ "ฉลาด" เหล่านี้ในส่วนคำสั่ง WHERE คือสร้างแผนแรงเดรัจฉานที่เรียบง่ายที่เพิ่งสแกนตารางทั้งหมดกรองแถวตามที่ไป โดยไม่ใช้ประโยชน์จากดัชนีใด ๆ

ไม่น่าแปลกใจสิ่งนี้ทำให้พวกเขาช้าอย่างสม่ำเสมอไม่ว่าค่าพารามิเตอร์ / ตัวแปรคืออะไร


8

ไม่มีวิธีที่รับประกันว่าจะบังคับให้เซิร์ฟเวอร์ SQL ดำเนินการตามเงื่อนไขข้อในลำดับที่เฉพาะเจาะจง เครื่องมือเพิ่มประสิทธิภาพจะประเมินผลตามลำดับที่เห็นว่าเหมาะสม

สิ่งที่คุณสามารถทำได้คือสิ่งนี้:

IF @LinkMode IS NULL
BEGIN
    select ...
    from ...
    WHERE (myColumn IN (...very long time exeted query...))
         ...
         ...
END
ELSE
BEGIN
    select ...
    from ...
    WHERE ...
         ...
END

3

หากเป็นตัวเลือกให้ใช้คำสั่ง IF เพื่อดำเนินการกับแบบฟอร์มที่เหมาะสมของแบบสอบถาม นอกจากนี้ใน SQL คุณบอกเอ็นจิ้น db ว่าต้องทำอย่างไรไม่ใช่ทำอย่างไร - สิ่งต่าง ๆ จะไม่ถูกดำเนินการตั้งแต่ต้นจนจบ มันยากที่จะทำนายว่ามันจะทำอะไร คุณอาจจะรู้เรื่องนี้แม้ว่า;)


2

SQL แบบไดนามิกอาจจะทำงานมากเกินไปเนื่องจากในกรณีที่เพิ่มประสิทธิภาพการค้นหาควรจะได้รับค่าที่แท้จริงที่ใช้เวลา(ทำผมที่ถูกต้องหากฉันผิดฉันจริงไม่แน่ใจ แต่ดูเหมือนจะจำใช้มันสำหรับสถานการณ์ที่คล้ายคลึงกัน) แต่ฉันกับคนอื่น ๆ ในประโยคนี้ในประโยค IF / ELSE จะให้บริการคุณดีที่สุดเพราะเป็นวิธีที่ง่ายและง่ายที่สุดที่จะทำสิ่งที่ต้องการ

สำหรับการอ้างอิงในอนาคตในกรณีที่คุณยังไม่ได้ใช้ไซต์ที่น่าเกลียดอย่างน่าเกลียดที่มีตัวอย่างการทำงานสำหรับ SQL แบบไดนามิกสามารถพบได้ที่นี่เช่น: http://sqlusa.com/bestpractices/dynamicsql/


1

ฉันอยากจะแนะนำโครงสร้าง IF / ELSE .. หากด้วยเหตุผลใดก็ตามที่ไม่ได้ผลสำหรับคุณคุณสามารถพิจารณาใช้ตัวเลือก WITH RECOMPILE เสมอ


คุณอาจอธิบายอย่างละเอียดเกี่ยวกับสิ่งที่ "ถ้า / อื่นสร้าง" อาจมีลักษณะอย่างไร : D
jcolebrand

ฉันจะแนะนำให้ใช้ OPTION (WITH RECOMPILE) เนื่องจากจะสร้างแผนในอุดมคติทุกครั้ง - ความล่าช้าในการคอมไพล์จะเพิ่มโอเวอร์เฮด แต่ฉันคิดว่ามันจะดีกว่าโดยรวมในกรณีนี้
SqlRyan
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.