2012-06-13 70 views
34

Tôi có một số mã .NET để kiểm tra sự tồn tại của một bản ghi SQL ở một khoảng thời gian vừa phải cao. Tôi đang tìm cách kiểm tra này là "rẻ" . càng tốt"SELECT TOP 1 1" VS "IF EXISTS (SELECT 1"

tôi đang tự hỏi những đặc điểm của hai truy vấn:

IF EXISTS(SELECT 1 
      FROM BigTable 
      WHERE SomeColumn = 200) 
    SELECT 1 AS FOUND 
ELSE 
    SELECT 0 AS FOUND 

VS

SELECT TOP 1 1 
FROM BigTable 
WHERE SomeColumn = 200 

cả hai đều tạo ra kế hoạch thực hiện tương tự Nhưng SELECT TOP 1 1 dường như thực hiện nhanh hơn.: Ít truy vấn để phân tích cú pháp và khi nào không tìm thấy bản ghi, nó sẽ gửi ít xuống đường ống. Tôi cũng giả sử nó chạy nhanh hơn ở máy khách bởi vì tôi chỉ cần kiểm tra Record Count, thay vì marshaling giá trị trả về của IF EXISTS.

Hầu hết các lợi ích hiệu suất đều không đáng kể. Nhưng nếu cả hai đều trả về cùng một kết quả, thì tại sao không chọn phương thức nhanh hơn ?

Có phải "CHỌN TOP 1 1" THEE cách tốt nhất để kiểm tra sự tồn tại của bản ghi trong .NET?

(Chúng tôi sử dụng .NET 3.5, và tôi đang cố gắng tránh LINQ vì nó không được sử dụng ở nơi khác trong ứng dụng. Chúng tôi cũng có một số ứng dụng VB6 cũ mà chúng tôi đang di chuyển/viết lại, vì vậy chúng có thể cần thực hiện tốt.)

CHỈNH SỬA: Chỉ cần thêm một chút chi tiết về thiết kế. Bản ghi này là "tiêu đề". Có một bảng khác có các bản ghi con sẽ được đọc/phân tích cú pháp khi tìm thấy tiêu đề này. Việc thiếu hồ sơ là một điều tốt: không có việc phải làm.

EDIT2: Việc thiếu bản ghi đáp ứng điều kiện sẽ xảy ra thường xuyên hơn. Họ đến trong những con sóng lẻ tẻ.

+0

Nó không hoạt động khi không có hàng đáp ứng điều kiện. Thử 'SELECT TOP 1 1 FROM BigTable trong đó 1 = 0' –

+0

Đó là vấn đề. Tôi đang kiểm tra sự tồn tại của một hàng DOES đáp ứng được điều kiện. –

+1

Sau "EDIT": Tại sao bạn kiểm tra sự tồn tại của bản ghi thay vì chỉ cố gắng tìm nạp bản ghi duy nhất phù hợp với tiêu chí của bạn? Nếu tìm nạp (chọn) trả về không có bản ghi, bạn không có việc phải làm và nó không đắt hơn nhiều sau đó chỉ kiểm tra sự tồn tại của bản ghi đó. Nếu nó trả về bản ghi, bạn có dữ liệu tiêu đề của bạn được tải và chỉ lưu một truy vấn cơ sở dữ liệu. –

Trả lời

31

Tôi muốn giới thiệu IF EXISTS(SELECT * ...), trừ khi điều này thực sự gây ra vấn đề về hiệu suất. Nó thể hiện mục đích của truy vấn theo cách hiểu tốt hơn nhiều so với các lựa chọn thay thế.

Tôi muốn tránh COUNT(*) (như trong câu trả lời hiện tại) trừ khi bạn thực sự cần số lượng hàng từ bảng.

Nếu bạn muốn "hiệu quả" của việc kiểm tra rowcount từ kết quả, tôi có thể đi cho:

select 1 where exists(select * from BigTable where SomeColumn=200) 

nào tạo ra kết quả tương tự như thiết lập truy vấn thứ hai của bạn (0 hoặc 1 hàng)

+3

Hoàn toàn đồng ý. Nghe có vẻ rõ ràng, nhưng làm cho nó rõ ràng để tối ưu hóa những gì chúng tôi đang cố gắng làm (kiểm tra xem một cái gì đó tồn tại) thường là bước đầu tiên trong việc thực hiện lành mạnh. –

+0

Điều này có vẻ tuyệt vời! Nhưng "SELECT TOP 1 1" vẫn nhanh hơn một chút so với kế hoạch thực hiện thực tế. Có lẽ nếu đây là một thủ tục? –

+0

@EricSwanson - có thể đi xuống tất cả các loại minutiae trong thiết lập máy chủ của bạn (về phần cứng, phần mềm và cách sử dụng, bảng lớn thực sự là bao nhiêu, chỉ mục nào có sẵn, v.v.). Tôi chỉ chạy một vài bài kiểm tra với một bảng có kích thước vừa phải và không thể phân chia sự khác biệt giữa chúng. –

-11

Không chắc về SQLServer nhưng trong cơ sở dữ liệu khác các phương pháp tiêu chuẩn là:

SELECT COUNT(*) FROM BigTable where SomeCol = 200; 

hiệu quả thực tế phụ thuộc vào bạn chỉ số vv

+10

Nếu bạn chỉ quan tâm đến sự tồn tại/không tồn tại của các hàng, tôi sẽ cảnh báo rõ ràng * chống lại * bằng cách sử dụng 'COUNT (*) ', vì nó phải xử lý toàn bộ * bảng để tính toán kết quả (trong khi' TOP 1' hoặc 'EXISTS' có thể dừng sau khi một hàng phù hợp đã được tìm thấy) –

+3

Đồng ý với @Damien_The_Unbeliever - bạn không bao giờ nên sử dụng "đếm" nếu bạn chỉ quan tâm đến "tồn tại" - điều đó gây ra thêm công việc –

9

Đây là những gì bạn muốn thay vì báo cáo kết quả NẾU

SELECT ISNULL(
    (SELECT TOP 1 1 FROM BigTable where SomeCol = 200), 0); 
1

tôi chắc chắn sẽ đi cho tùy chọn thứ 2:

SELECT TOP 1 1 
FROM BigTable 
WHERE SomeColumn = 200 

các kế hoạch thực hiện đơn giản và hiệu quả ngay cả khi I/O và CPU số chủ yếu là giống nhau.

Các vấn đề liên quan