วิธีที่ดีที่สุดในการใช้การค้นหาที่ถูกกรอง


17

ฉันอยากจะถามคุณความคิดเห็นของคุณเมื่อต้องใช้แบบฟอร์มการค้นหาที่กรองแล้ว ลองจินตนาการถึงกรณีต่อไปนี้:

  • 1 ตารางขนาดใหญ่พร้อมคอลัมน์จำนวนมาก
  • มันอาจเป็นสิ่งสำคัญที่จะบอกว่า SQL Server นี้

คุณต้องใช้แบบฟอร์มเพื่อค้นหาข้อมูลในตารางนี้และในแบบฟอร์มนี้คุณจะมีช่องทำเครื่องหมายหลายช่องที่อนุญาตให้คุณคิดค่าใช้จ่ายในการค้นหานี้

ตอนนี้คำถามของฉันที่นี่ข้อใดต่อไปนี้ควรเป็นวิธีที่ดีที่สุดในการใช้การค้นหา

  1. สร้างกระบวนงานที่เก็บไว้ด้วยแบบสอบถามภายใน โพรซีเดอร์ที่เก็บไว้นี้จะตรวจสอบว่าพารามิเตอร์ได้รับจากแอปพลิเคชั่นหรือไม่และในกรณีที่พวกเขาไม่ได้รับไวด์การ์ดจะถูกใส่ในแบบสอบถาม

  2. สร้างแบบสอบถามแบบไดนามิกที่สร้างขึ้นตามสิ่งที่ได้รับจากแอปพลิเคชัน

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

โปรดบอกฉันว่าอะไรคือแนวทางที่ดีที่สุดในการต่อต้านของคุณ


คุณระบุด้านล่างว่าคุณมีแนวโน้มที่จะแก้ปัญหาแบบไดนามิก เยี่ยมยอดเพียงตรวจสอบให้แน่ใจว่าคุณระบุตัวกรองที่เป็นไปได้และมีดัชนีที่รองรับ ตราบใดที่แบบสอบถามถูกสร้างขึ้นอย่างสม่ำเสมอควรมีประสิทธิภาพ
Matthew Flynn

คำตอบ:


10

คุณอาจต้องการดูคำตอบของคำถามที่คล้ายกันนี้ที่นี่: /programming/11329823/add-where-clauses-to-sql-dynamically-programmatically

เราพบว่า SPROC ซึ่งใช้พารามิเตอร์ตัวเลือกมากมายและใช้ตัวกรองดังนี้:

CREATE PROC MyProc (@optionalParam1 NVARCHAR(50)=NULL, @optionalParam2 INT=NULL)
AS 
...
SELECT field1, field2, ... FROM [Table]
WHERE 
  (@optionalParam1 IS NULL OR MyColumn1 = @optionalParam1)
  AND (@optionalParam2 IS NULL OR MyColumn2 = @optionalParam2)

จะแคชแผนการดำเนินการครั้งแรกที่เรียกใช้ด้วย (เช่น@optionalParam1 = 'Hello World', @optionalParam2 = NULL) แต่จากนั้นดำเนินการอย่างน่าสังเวชถ้าเราผ่านชุดพารามิเตอร์ทางเลือกอื่น (เช่น@optionalParam1 = NULL, @optionalParam2 = 42) (และแน่นอนว่าเราต้องการประสิทธิภาพของแผนแคชดังนั้นจึงWITH RECOMPILEออก)

ข้อยกเว้นที่นี่คือหากมีตัวกรอง MANDATORY อย่างน้อยหนึ่งตัวในแบบสอบถามซึ่งเลือกอย่างสูงและจัดทำดัชนีอย่างถูกต้องนอกเหนือจากพารามิเตอร์ทางเลือกแล้ว PROC ด้านบนจะทำงานได้ดี

อย่างไรก็ตามหากตัวกรองทั้งหมดเป็นตัวเลือกความจริงที่น่ากลัวกว่านั้นคือ sql แบบแปรผันตามจริงจะมีประสิทธิภาพดีกว่า (เว้นแต่คุณจะเขียน PROCS สแตติกที่แตกต่างกัน N!

SQL แบบไดนามิกด้านล่างจะสร้างและแคชแผนที่แตกต่างกันสำหรับการเปลี่ยนค่าพารามิเตอร์ Query แต่ละครั้ง แต่อย่างน้อยแต่ละแผนจะถูกปรับให้เหมาะกับการสืบค้นเฉพาะ (ไม่สำคัญว่าจะเป็น PROC หรือ Adhoc SQL หรือไม่ ตราบใดที่คำค้นหาเป็นพารามิเตอร์พวกเขาจะถูกแคช)

ดังนั้นการตั้งค่าของฉันสำหรับ:

DECLARE @SQL NVARCHAR(MAX)        

-- Mandatory / Static part of the Query here
SET @SQL = N'SELECT * FROM [table] WHERE 1 = 1'

IF @OptionalParam1 IS NOT NULL        
    BEGIN        
        SET @SQL = @SQL + N' AND MyColumn1 = @optionalParam1'    
    END        

IF @OptionalParam2 IS NOT NULL        
    BEGIN        
        SET @SQL = @SQL + N' AND MyColumn2 = @optionalParam2'    
    END        

EXEC sp_executesql @SQL,        
    N'@optionalParam1 NVARCHAR(50), 
      @optionalParam2 INT'
    ,@optionalParam1 = @optionalParam1
    ,@optionalParam2 = @optionalParam2

ฯลฯ ไม่สำคัญว่าเราจะส่งผ่านพารามิเตอร์ที่ซ้ำซ้อนไปยัง sp_executesql หรือไม่ซึ่งจะถูกละเว้น เป็นที่น่าสังเกตว่า ORM ของ Linq2SQL และ EF ใช้พารามิเตอร์แบบไดนามิก sql ในลักษณะที่คล้ายกัน


1
ใช่ฉันคิดอย่างนั้นนี่เป็นตัวเลือกที่ฉันเลือก แค่อยากให้แน่ใจว่ามันเป็นสิ่งที่ดี ขอบคุณสำหรับคำตอบ
j0N45

"หากคำสั่ง SQL ถูกดำเนินการโดยไม่มีพารามิเตอร์ SQL Server จะกำหนดพารามิเตอร์คำสั่งภายในเพื่อเพิ่มความเป็นไปได้ในการจับคู่กับแผนการดำเนินการที่มีอยู่กระบวนการนี้เรียกว่าการกำหนดพารามิเตอร์แบบง่าย" ดังนั้นโดยทั่วไปโปรแกรมสามารถใช้บางอย่างเช่น "where filenumber =" + filename แน่นอนว่าเปิดกระป๋องเวิร์ม แต่เป็นหัวข้อที่แตกต่าง ;-) #
24732 Codism

5

เริ่มจากสิ่งที่คุณคิดว่าง่ายต่อการนำไปใช้ (ฉันเดาว่าตัวเลือก 2) จากนั้นวัดประสิทธิภาพสำหรับข้อมูลโลกแห่งความจริง เริ่มต้นการปรับให้เหมาะสมเมื่อจำเป็นเท่านั้นไม่ใช่ล่วงหน้า

ทั้งนี้ขึ้นอยู่กับความซับซ้อนของตัวกรองการค้นหางานของคุณอาจไม่สามารถแก้ไขได้อย่างง่ายดายหากไม่มี SQL แบบไดนามิก ดังนั้นแม้ว่าคุณจะใช้กระบวนงานที่เก็บไว้ซึ่งส่วนใหญ่อาจจะไม่เพิ่มประสิทธิภาพตามที่คุณสงสัยอยู่แล้ว ในทางกลับกันถ้ามันช่วยได้มีคำแนะนำหลายประเภท (ดูhttp://www.simple-talk.com/sql/performance/controlling-execution-plans-with-hints/ ) คุณสามารถเพิ่ม SQL เข้าไปได้ แบบสอบถามแบบไดนามิกหรือไม่เพื่อช่วยให้เซิร์ฟเวอร์ SQL เพื่อเพิ่มประสิทธิภาพแผนการดำเนินการ


ฉันได้ใช้ตัวเลือก 2 แล้วและฉันคิดว่ามันเป็นวิธีที่ดีที่สุดส่วนใหญ่เป็นเพราะ wildcard จะลดประสิทธิภาพลงอย่างมากอย่างไรก็ตามฉันกำลังเสียสละการบำรุงรักษาเนื่องจากจะเพิ่มความซับซ้อนในรหัส ฉันแค่อยากจะรู้ว่าใครบางคนรู้จักตัวเลือกที่ดีกว่าสำหรับสถานการณ์แบบนี้
j0N45

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