2012-02-26 10 views
10

tôi sử dụng để viết statments sql nhưlà "nơi (ParamID = @ParamID) OR (@ParamID = -1)" một thói quen tốt trong việc lựa chọn sql

select * from teacher where (TeacherID = @TeacherID) OR (@TeacherID = -1) 

read more

và vượt qua @TeacherID value = -1 để chọn tất cả giáo viên

bây giờ tôi lo lắng về hiệu suất bạn có thể cho tôi biết đó là thực hành tốt hay xấu?

cảm ơn rất nhiều

+1

George, bạn không thể hình dung được câu hỏi của mình 'nóng' như thế nào. Bạn vừa tạo ra một kết hợp tuyệt vời của 'thực hành tốt nhất' và 'SQL' trong một câu hỏi duy nhất. Đã thêm +1, sẽ thêm +100 nếu tôi có thể. –

+0

Tôi thường viết hai truy vấn riêng biệt theo đề xuất của @Jeff O. Ngoài ra, bạn có thể muốn đọc về tham số sniffing. SQL động và RECOMPILE có thể đắt hơn trong trường hợp này - chúng tôi chỉ có hai trường hợp riêng biệt. –

Trả lời

6

Nếu TeacherID được lập chỉ mục và bạn đang đi qua một giá trị khác hơn -1 như TeacherID để tìm kiếm thông tin chi tiết của một giáo viên cụ thể sau đó truy vấn này sẽ kết thúc làm một bảng quét toàn bộ chứ không phải là lựa chọn tiềm năng hiệu quả hơn của tìm kiếm vào chỉ mục để lấy các chi tiết của giáo viên cụ thể ...

... Trừ khi bạn đang sử dụng SQL 2008 SP1 CU5 trở lên và sử dụng gợi ý OPTION (RECOMPILE). Xem Dynamic Search Conditions in T-SQL để biết bài viết cuối cùng về chủ đề.

+1

+1 cho liên kết đến công việc của Erland. Đó hoàn toàn là câu trả lời. – NotMe

6

Chúng tôi sử dụng quy trình này rất hạn chế trong các thủ tục được lưu trữ.

Vấn đề là công cụ cơ sở dữ liệu không thể giữ một kế hoạch truy vấn tốt cho nó. Khi xử lý nhiều dữ liệu, điều này có thể có tác động tiêu cực nghiêm trọng về hiệu suất.

Tuy nhiên, đối với các tập dữ liệu nhỏ hơn (tôi muốn nói dưới 1000 bản ghi, nhưng đó là phỏng đoán) nó sẽ ổn. Bạn sẽ phải thử nghiệm trong môi trường cụ thể của bạn.

Nếu trong quy trình được lưu trữ, bạn có thể muốn bao gồm thứ gì đó như tùy chọn WITH RECOMPILE sao cho số plan is regenerated on each execution. Điều này cho biết thêm (hơi) đến thời gian cho mỗi lần chạy, nhưng qua một số lần chạy có thể thực sự làm giảm thời gian thực hiện trung bình. Ngoài ra, điều này cho phép cơ sở dữ liệu kiểm tra truy vấn thực tế và "short circuit" các phần không cần thiết trên mỗi cuộc gọi.

Nếu bạn đang trực tiếp tạo SQL và chuyển nó qua, thì tôi khuyên bạn nên tạo phần xây dựng sql của bạn thông minh hơn một chút để nó chỉ bao gồm một phần của mệnh đề where bạn thực sự cần.


Đường dẫn khác bạn có thể xem xét là sử dụng UNION TẤT CẢ các truy vấn trái ngược với tham số tùy chọn. Ví dụ:

SELECT * FROM Teacher WHERE (TeacherId = @TeacherID) 
UNION ALL 
SELECT * FROM Teacher WHERE (@TeacherId = -1) 

Điều này thực sự hoàn thành điều tương tự; tuy nhiên, kế hoạch truy vấn có thể lưu vào bộ nhớ cache. Chúng tôi cũng đã sử dụng phương pháp này ở một vài nơi và thấy các cải tiến hiệu suất khi sử dụng WITH RECOMPILE. Chúng tôi không làm điều này ở khắp mọi nơi bởi vì một số truy vấn của chúng tôi vô cùng phức tạp và tôi muốn có hiệu suất hơn là làm phức tạp thêm chúng.

Cuối cùng, bạn cần thực hiện nhiều thử nghiệm.


Có phần thứ hai ở đây bạn nên xem xét lại. SELECT *. It is ALWAYS preferable to actually name the columns you want returned và để đảm bảo rằng bạn đang chỉ trả lại những thứ bạn thực sự cần. Di chuyển dữ liệu qua các ranh giới mạng là rất tốn kém và bạn thường có thể nhận được một số tiền hợp lý về tăng hiệu suất chỉ đơn giản bằng cách xác định chính xác những gì bạn muốn. Ngoài ra nếu những gì bạn cần là rất hạn chế bạn đôi khi có thể làm covering indexes để các công cụ cơ sở dữ liệu thậm chí không phải chạm vào các bảng bên dưới để có được dữ liệu bạn muốn.

+0

'UNION ALL' của bạn giả định' TeacherId' không bao giờ có thể là -1, vì vậy tôi tự hỏi, có thể đặt điều đó trong một ràng buộc bằng cách nào đó mà SQL Server có thể tự mình tìm ra một kế hoạch tốt? – hvd

+2

@hvd: Rất hiếm khi ai đó sử dụng số âm cho Id. Đến mức nếu bạn đang trong tình huống này thì bạn chỉ cần vượt qua null và kiểm tra cho rằng thay vì sử dụng -1 – NotMe

+0

Tôi biết điều đó, nhưng quan điểm của tôi là tối ưu hóa truy vấn SQL Server không. – hvd

3

Nếu bạn thực sự lo lắng về hiệu suất, bạn có thể chia nhỏ quy trình của mình để gọi hai trình phát khác nhau: một cho tất cả bản ghi và một dựa trên tham số.

If @TeacherID = -1 
    exec proc_Get_All_Teachers 
else 
    exec proc_Get_Teacher_By_TeacherID @TeacherID 

Mỗi người có thể được tối ưu hóa riêng lẻ.

Đó là hệ thống của bạn, so sánh hiệu suất. Cân nhắc tối ưu hóa lựa chọn phổ biến nhất. Nếu hầu hết người dùng sẽ chọn một bản ghi duy nhất, thì tại sao họ lại có khả năng chuẩn bị sẵn sàng cho số ít người đó là tất cả giáo viên (Và nên có một kỳ vọng hợp lý về hiệu suất).

Tôi biết một truy vấn chọn duy nhất là dễ bảo trì hơn, nhưng tại một số điểm dễ bảo trì cuối cùng cũng nhường chỗ cho hiệu suất.

+0

Đối với một tình huống đơn giản như những gì OP cho thấy, điều này sẽ là tốt. Tuy nhiên, nó không thể duy trì nếu số tham số tìm kiếm tùy chọn lớn hơn 1. Ví dụ, nếu là 2 bạn sẽ phải có 4 s'procs ... – NotMe

+0

@ChrisLively - SQL Server 2008 sẽ cho phép truyền tham số giá trị bảng. Câu lệnh select bên trong proc có thể sử dụng câu lệnh đó thay vì một tham số giá trị đơn. – JeffO