Lợi ích chung của bảng biểu hiện (CTE)?


21

Từ msd :

Không giống như bảng dẫn xuất, CTE có thể tự tham chiếu và có thể được tham chiếu nhiều lần trong cùng một truy vấn.

Tôi đang sử dụng CTE khá nhiều, nhưng tôi chưa bao giờ nghĩ sâu về lợi ích của việc sử dụng chúng.

Nếu tôi tham chiếu CTE nhiều lần trong cùng một truy vấn:

  • Có bất kỳ lợi ích hiệu suất?
  • Nếu tôi đang tự tham gia, SQL Server có quét các bảng mục tiêu hai lần không?

2
Profiler sẽ cho bạn biết nếu nó quét hai lần. IMHO, CTE là tuyệt vời cho đệ quy.
Dan Andrew

3
Không có câu trả lời khó khi trình tối ưu hóa truy vấn đang hoạt động. Một số truy vấn sẽ thấy lợi ích hiệu suất, một số sẽ không. Đôi khi, sử dụng bảng tạm thời thay vì CTE sẽ nhanh hơn, đôi khi không.

Câu trả lời:


25

Theo quy định, CTE sẽ KHÔNG BAO GIỜ cải thiện hiệu suất .

Một CTE về cơ bản là một cái nhìn dùng một lần. Không có số liệu thống kê bổ sung được lưu trữ, không có chỉ mục, v.v ... Nó có chức năng như một cách viết tắt cho một truy vấn con.

Theo tôi, họ có thể DỄ DÀNG sử dụng quá mức (tôi thấy rất nhiều sự lạm dụng mã trong công việc của tôi). Một số câu trả lời hay có ở đây, nhưng nếu bạn cần tham khảo một cái gì đó nhiều hơn một lần, hoặc đó là hơn vài trăm nghìn hàng, #tempthay vào đó hãy đặt nó vào một bảng và lập chỉ mục.


3
Đồng ý. Ngoại trừ các CTE đệ quy, sau đó chúng chỉ đơn giản là hỗ trợ khả năng đọc
gbn

Điều gì sẽ xảy ra nếu CTE chỉ trả về một vài hàng (để chúng có thể được lưu trong bộ nhớ) rất tốn kém để tính toán (tổng hợp trên một bảng lớn) và kết quả đó được sử dụng nhiều lần? Điều đó sẽ cải thiện hiệu suất, không nên? (ít nhất đó là trải nghiệm của tôi với PostgreSQL và Oracle nơi bảng tạm thời được sử dụng rất hiếm khi)
a_horse_with_no_name

2
@a_horse_with_no_name - nó sẽ tương đương với việc biến nó thành một truy vấn con. Nếu kết quả được sử dụng nhiều lần trong một truy vấn, nó sẽ được sử dụng lại và không được tính toán lại. Nếu nó được sử dụng trong nhiều truy vấn, thì đó CTElà một lựa chọn tồi vì các kết quả bị loại bỏ sau truy vấn đầu tiên.
JNK

@JNK: cảm ơn. Có vẻ như SQL Server hoạt động khác ở đây.
a_horse_with_no_name

Một số người tìm thấy CTE dễ đọc hơn trong một số trường hợp nhất định FWIW stackoverflow.com/a/11170918/32453
rogerdpack

14

Một nơi bên cạnh đệ quy nơi tôi thấy CTE cực kỳ hữu ích là khi tạo các truy vấn báo cáo phức tạp. Tôi sử dụng một loạt các CTE để lấy các khối dữ liệu tôi cần và sau đó kết hợp trong lựa chọn cuối cùng. Tôi thấy chúng dễ bảo trì hơn so với thực hiện cùng một thứ với nhiều bảng dẫn xuất hoặc 20 phép nối và tôi thấy rằng tôi có thể yên tâm hơn rằng nó trả về dữ liệu chính xác mà không ảnh hưởng đến nhiều bản ghi do có nhiều mối quan hệ trong tất cả các tham gia khác nhau. Hãy để tôi đưa ra một ví dụ nhanh:

;WITH Conferences (Conference_id)
AS 
(select  m.Conference_id
FROM mydb.dbo.Conference m 
WHERE client_id = 10
    and Conference_id in 
            (select Conference_id from mydb.dbo.Expense 
            where amount <>0
            and amount is not null)
     )
--select * from Conferences
,MealEaters(NumberMealEaters, Conference_id, AttendeeType)
AS
(Select count(*) as NumberMealEaters, m.Conference_id,  AttendeeType 
from mydb.dbo.attendance ma 
join Conferences m on m.Conference_id = ma.Conference_id
where (ma.meals_consumed>0 or meals_consumed is null)and attended = 1
group by m.Conference_id)
--select * from MealEaters

,Expenses (Conference_id,expense_date, expenseDescription,  RecordIdentifier,amount)
AS
(select Conference_id,max(expense_date) as Expense_date, expenseDescription,  RecordIdentifier,sum(amount) as amount
    FROM
        (SELECT Conference_id,expense_date,  amount, RecordIdentifier
        FROM mydb.dbo.Expense
        WHERE  amount <> 0 
            and Conference_id IN 
            (SELECT  Conference_id
            FROM mydb.dbo.Conferences ) 
        group by Conference_id, RecordIdentifier) a
)
--select * from Expenses
Select m.Conference_id,me.NumberMealEaters, me.AttendeeType, e.expense_date,         e.RecordIdentifier,amount
from Conferences m
join mealeaters me on m.Conference_id = me.Conference_id
join expenses e on e.Conference_id = m.Conference_id

Vì vậy, bằng cách tách ra các khối thông tin khác nhau mà bạn muốn, bạn có thể kiểm tra từng phần riêng lẻ (sử dụng các lựa chọn nhận xét, bằng cách bỏ qua từng phần riêng lẻ và chỉ chạy theo lựa chọn đó) và nếu bạn cần thay đổi chi phí tính toán (trong ví dụ này), nó dễ tìm hơn so với khi tất cả chúng được trộn với nhau thành một truy vấn lớn. Tất nhiên các truy vấn báo cáo thực tế tôi sử dụng này thường phức tạp hơn nhiều so với ví dụ.


1
Chỉ để báo cáo truy vấn? Các hệ thống tôi làm việc hàng ngày có các truy vấn giao dịch phức tạp. Điều kỳ lạ là các truy vấn báo cáo của chúng tôi thường là một số trong những câu hỏi đơn giản hơn. (Tất nhiên là các truy vấn CRUD không tham gia tầm thường).
Kevin Cathcart

Tôi đã sử dụng nó làm ví dụ bởi vì những thứ đó thường phức tạp nhất ở đây
HLGEM

+1 đôi khi một truy vấn logic hơn (người có thể đọc được) thích hợp hơn một truy vấn có khả năng thực hiện tốt hơn.
onedaywhen

Vâng. Cho rằng một CTE thường sẽ tạo ra cùng một kế hoạch kết quả, tôi thấy không có lý do gì để tạo ra những quái vật đa nhiệm, lồng ghép khủng khiếp - khi chúng ta có thể bố trí từng thành phần một cách trực quan theo thứ tự mà chúng cần. Tôi nhập các tệp XML và thực hiện nhiều thao tác nhào lộn khác nhau để đưa dữ liệu vào đúng biểu mẫu, điều này sẽ không thể chịu được khi viết / đọc mà không có CTE. (Một số mã cũ của tôi có thể có các truy vấn con khủng khiếp suốt cả vòng!)
underscore_d

0

Như mọi khi nó phụ thuộc nhưng có những trường hợp hiệu suất được cải thiện rất nhiều. Tôi thấy nó với các câu lệnh INSERT INTO SELECT trong đó bạn sử dụng CTE cho lựa chọn và sau đó sử dụng nó trong INSERT INTO. Nó có thể phải làm với RCSI được thiết lập cho cơ sở dữ liệu nhưng đối với những thời điểm khi rất ít được chọn, nó có thể giúp ích khá nhiều.

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.