Phương pháp tốt nhất để thực hiện tìm kiếm được lọc


17

Tôi muốn hỏi bạn, ý kiến ​​của bạn khi nói đến việc thực hiện một hình thức tìm kiếm được lọc. Hãy tưởng tượng trường hợp sau:

  • 1 bàn lớn có nhiều cột
  • Điều quan trọng có thể nói là Máy chủ SQL này

Bạn cần triển khai một biểu mẫu để tìm kiếm dữ liệu trong bảng này và trong biểu mẫu này, bạn sẽ có một số hộp kiểm cho phép bạn chi phí tìm kiếm này.

Bây giờ câu hỏi của tôi ở đây là một trong những điều sau đây nên là cách tốt nhất để thực hiện tìm kiếm?

  1. Tạo một thủ tục được lưu trữ với một truy vấn bên trong. Quy trình được lưu trữ này sẽ kiểm tra xem các tham số có được cung cấp bởi ứng dụng hay không và trong trường hợp chúng không được cung cấp ký tự đại diện sẽ được đưa vào truy vấn.

  2. Tạo một truy vấn động, được xây dựng phù hợp với những gì được đưa ra bởi ứng dụng.

Tôi hỏi điều này bởi vì tôi biết rằng SQL Server tạo một kế hoạch thực hiện khi thủ tục được lưu trữ được tạo ra, để tối ưu hóa hiệu suất của nó, tuy nhiên bằng cách tạo một truy vấn động bên trong thủ tục được lưu trữ, liệu chúng ta có hy sinh tối ưu hóa có được bởi kế hoạch thực hiện không?

Xin vui lòng cho tôi biết những gì sẽ là cách tiếp cận tốt nhất trong ý kiến ​​của bạn.


Bạn nêu dưới đây rằng bạn đang có xu hướng về giải pháp năng động. Điều đó thật tuyệt, chỉ cần đảm bảo bạn liệt kê các bộ lọc có thể và có các chỉ mục hỗ trợ chúng. Miễn là các truy vấn được xây dựng nhất quán, chúng sẽ có hiệu quả.
Matthew Flynn

Câu trả lời:


10

Bạn có thể muốn xem câu trả lời cho câu hỏi tương tự này tại đây: /programming/11329823/add-where-clauses-to-sql-dynamical-programmatically

Chúng tôi đã phát hiện ra rằng một XUÂN có một loạt các tham số tùy chọn và thực hiện bộ lọc như thế này:

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)

sẽ lưu trữ kế hoạch thực hiện đầu tiên mà nó được chạy với (ví dụ @optionalParam1 = 'Hello World', @optionalParam2 = NULL) nhưng sau đó thực hiện một cách thảm hại nếu chúng ta truyền cho nó một tập các tham số tùy chọn khác (ví dụ @optionalParam1 = NULL, @optionalParam2 = 42). (Và rõ ràng là chúng tôi muốn hiệu suất của kế hoạch lưu trữ, vì vậy đã WITH RECOMPILEhết)

Một ngoại lệ ở đây là nếu C ALNG có ít nhất một bộ lọc MANDATORY trên truy vấn được chọn lọc CAO và được lập chỉ mục đúng, ngoài các tham số tùy chọn, thì PROC ở trên sẽ hoạt động tốt.

Tuy nhiên, nếu TẤT CẢ các bộ lọc là tùy chọn, thì sự thật khá tệ là sql động được tham số hóa thực sự hoạt động tốt hơn (trừ khi bạn viết PROCS tĩnh khác nhau cho mỗi hoán vị của các tham số tùy chọn).

SQL động như dưới đây sẽ tạo và lưu trữ một kế hoạch khác nhau cho mỗi hoán vị của các tham số Truy vấn, nhưng ít nhất mỗi kế hoạch sẽ được 'điều chỉnh' cho truy vấn cụ thể (không quan trọng đó là SQL PROC hay Adhoc - như miễn là chúng là các truy vấn được tham số hóa, chúng sẽ được lưu trữ)

Vì vậy, sở thích của tôi cho:

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

v.v ... Sẽ không có vấn đề gì nếu chúng ta chuyển các tham số dự phòng vào sp_executesql - chúng bị bỏ qua. Điều đáng chú ý là các ORM như Linq2Query và EF sử dụng sql động được tham số hóa theo cách tương tự.


1
Vâng tôi nghĩ vậy, đây là lựa chọn mà tôi chọn. Chỉ muốn chắc chắn rằng nó là một trong những tốt. Cảm ơn bạn đã phản hồi.
j0N45

"Nếu một câu lệnh SQL được thực thi mà không có tham số, SQL Server tham số hóa câu lệnh bên trong để tăng khả năng khớp nó với kế hoạch thực hiện hiện có. Quá trình này được gọi là tham số hóa đơn giản." Vì vậy, về cơ bản chương trình có thể sử dụng một số thứ như "where filenumber =" + tên tệp. Tất nhiên, điều đó mở ra một lon giun nhưng đó là một chủ đề khác ;-)
Codism

5

Bắt đầu với bất cứ điều gì bạn nghĩ là dễ thực hiện hơn (tôi đoán tùy chọn 2). Sau đó đo hiệu suất cho dữ liệu thế giới thực. Chỉ bắt đầu tối ưu hóa khi cần thiết, không phải trước đó.

Nhân tiện, tùy thuộc vào mức độ phức tạp của các bộ lọc tìm kiếm của bạn, tác vụ của bạn có thể không được giải quyết dễ dàng nếu không có SQL động. Vì vậy, ngay cả khi bạn sử dụng một thủ tục được lưu trữ, điều đó rất có thể sẽ không làm tăng hiệu suất, như bạn đã nghi ngờ. Mặt khác, nếu nó hữu ích, có một số loại gợi ý (xem http://www.simple-talk.com/sql/performance/controlling-execut-plans-with-hints/ ) bạn có thể thêm vào SQL truy vấn, động hay không, để giúp máy chủ SQL tối ưu hóa kế hoạch thực hiện.


Chà, tôi đã thực hiện tùy chọn 2 và tôi nghĩ đó là cách tốt nhất, chủ yếu là vì các ký tự đại diện sẽ làm giảm đáng kể hiệu năng, tuy nhiên tôi đang hy sinh bảo trì, vì điều này sẽ làm tăng độ phức tạp trong mã. Tôi chỉ muốn biết nếu ai đó biết một lựa chọn tốt hơn cho những tình huống này.
j0N45

Tôi sẽ cho bạn một cuộc bỏ phiếu, nhưng tôi không có tiếng tăm xin lỗi.
j0N45
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.