Hiệu suất truy vấn


7

Tại sao

SELECT Barraportfolioname
FROM   portfolio
WHERE  id IN (SELECT DISTINCT i1.portfolioid
              FROM   Import i1
                     LEFT OUTER JOIN Import i2
                       ON i1.PortfolioID = i2.PortfolioID
                          AND i2.ImportSetID = 82
              WHERE  i1.ImportSetID = 83
                     AND i2.ID IS NULL)  

mất 0 giây trong khi truy vấn sau mất 5 giây.

SELECT DISTINCT p.BarraPortfolioName AS name
FROM   Import i1
       INNER JOIN Portfolio p
         ON p.ID = i1.PortfolioID
       LEFT OUTER JOIN Import i2
         ON i1.PortfolioID = i2.PortfolioID
            AND i2.ImportSetID = 82
WHERE  i1.ImportSetID = 83
       AND i2.ID IS NULL;  

Tôi đang sử dụng SQL Server. Cả hai bảng đều có các chỉ mục trên tất cả các cột đang được sử dụng trong truy vấn, ví dụ như portfolioid, id, importsetid.

Chỉnh sửa bởi gbn, dựa trên bình luận của OP

Họ nói rằng:

Điều này hoạt động tốt hơn nhiều so với hai truy vấn trước.

select
   BarraPortfolioName
from 
   (
   select distinct p.BarraPortfolioName,portfolioid
   from
        import i1
        inner join 
        portfolio p on p.id=i1.portfolioid
   where 
        importsetid = ?
   ) as p1
   left outer join
   (
   select distinct portfolioid 
   from import 
   where importsetid = ?
   ) as p2 on p1.portfolioid = p2.portfolioid
where 
   p2.portfolioid is null

6
Đăng các kế hoạch truy vấn
Gaius

Ở dạng hiện tại, câu hỏi này không thể trả lời được (và chắc chắn sẽ bị đóng nếu bạn để nó như thế này) - nhưng nếu có "số liệu thống kê xấu" sẽ hiển thị trong kế hoạch?
Jack nói hãy thử topanswers.xyz

1
Nhưng chắc chắn những người điều chỉnh truy vấn tốt có thể thấy sự khác biệt trong các truy vấn cách xa ...
Rob Farley

Tôi đã xem xét dữ liệu trong bảng của mình và thấy rằng tồn tại nhiều ánh xạ giữa các danh mục đầu tư, tức là một lần nhập được đặt cùng một danh mục đầu tư nhiều lần. Vì vậy, tôi đã viết lại truy vấn của mình thành: từ nhập trong đó importsetid =?) dưới dạng p2 trên p1.port portfolioid = p2.port portfolioid trong đó p2.port portfolioid là null ". Điều này hoạt động tốt hơn nhiều so với hai truy vấn trước.
techExplorer

1
Làm thế nào bạn có thể so sánh 0 giây với 0 giây với truy vấn được viết lại? Hãy thử với SET STATISTICS IO ON để so sánh các truy vấn 1 và 3
gbn

Câu trả lời:


9

Điều này giả định rằng cả hai đều cho kết quả như nhau

  • Đầu tiên là "bán tham gia" vì IN (truy vấn phụ) (DISTINCT không cần thiết)
    Điều này có nghĩa là truy vấn phụ có thể "đoản mạch"

  • Thứ 2 là một tham gia bên ngoài sau đó hạn chế, tiếp theo là tổng hợp DISTINCT.
    Đây là 3 hoạt động riêng biệt

"Đoản mạch" này là lý do chính cho sự khác biệt ngay cả với phép nối ngoài trong truy vấn phụ.

Đối với các truy vấn đơn giản hơn, truy vấn thứ 2 sẽ được tối ưu hóa cho cùng một kế hoạch với truy vấn thứ nhất vì nó giống nhau về mặt ngữ nghĩa. Nhiều khả năng phiên bản mới hơn, v.v.

Xem thêm để biết thêm (cùng logic, chỉ đảo ngược): Việc sử dụng logic KHÔNG liên quan đến các chỉ mục

Và điều này nói về "IN vs. THAM GIA so với EXISTS" từ người dùng SO Quassnoi trên trang web của anh ấy

Và một ví dụ SO tương tự: https://stackoverflow.com/a/7221395/27535


4

Hãy thử với:

SELECT
   (select p.BarraPortfolioName from Portfolio p where p.ID = i1.PortfolioID) AS name  
FROM Import i1  
WHERE i1.ImportSetID = 83 
group by i1.PortfolioID  
HAVING NOT EXISTS     
    (SELECT * FROM Import i2 
    WHERE i1.PortfolioID = i2.PortfolioID 
    AND i2.ImportSetID = 82);

Bởi vì những gì bạn muốn làm là tìm các i1.Port portfolioID khác nhau, lọc danh sách đó cho những cái không có trong tập tin nhập khẩu 82 và hiển thị tên cho các id đó.


Quả thực bạn truy vấn thậm chí còn tốt hơn truy vấn thứ 3. Thống kê cho truy vấn thứ 3: Bảng 'Nhập'. Số lượng quét 375, đọc logic 1222, đọc vật lý 0, Bảng 'Danh mục đầu tư'. Quét số 0, logic đọc 52140, đọc vật lý 0 Thống kê cho truy vấn của bạn: Bảng 'Danh mục đầu tư'. Quét số 0, đọc logic 3, đọc vật lý 0, Bảng 'Nhập'. Quét số 375, đọc logic 1172, đọc vật lý 0
techExplorer

Bạn có thể muốn tạo chỉ mục ixBazaki khi nhập (ImportsetID, Port portfolioID) - nếu bạn chưa có chỉ mục.
Rob Farley

3

Nếu bạn không có chỉ mục duy nhất trên BarraPort portfolioName, nó cần kiểm tra tất cả chúng để tìm các bản sao, điều này không cần thiết trong truy vấn đầu tiên vì mệnh đề IN của bạn xử lý điều đó cho bạn.

Hãy thử tạo một chỉ mục duy nhất (hoặc ràng buộc) và xem liệu điều này có lừa không. Hoặc thay đổi tập lệnh thứ hai bằng cách bỏ phần khác biệt và đặt GROUP BY p.id, p.BarraPortfolioNameở cuối. Điều này sẽ cho phép nó ngắn mạch quá trình phân biệt.


Bạn đang thiếu điểm. Đó là về việc đưa p.id vào nhóm.
Rob Farley

Xóa các bình luận trước đây khi tôi thấy những gì bạn có ý nghĩa với GROUP BYbây giờ. Tôi nghĩ rằng điều đó sẽ thay đổi ngữ nghĩa nhưng nếu BarraPortfolioNamekhông phải là duy nhất thì 2 truy vấn trong OP dù sao cũng khác nhau về mặt ngữ nghĩa vì cái đầu tiên cũng cần DISTINCTđược thêm vào. Tôi vẫn thấy trong thử nghiệm rằng truy vấn 1 sử dụng bán tham gia và truy vấn 2 không mặc dù vậy OP chỉ nên bám vào 1 IMO.
Martin Smith

Vâng Mệnh đề từ nên là:
Rob Farley

TỪ nhập i1 TRÁI NGOÀI THAM GIA Nhập i2 TRÊN i1.Port portfolioID = i2.Port portfolioID VÀ i2.ImportSetID = 82 INNER THAM GIA Danh mục đầu tư p ON p.ID = i1.Port portfolioID
Rob Farley

... và đây là một vấn đề với QO mà nhóm sản phẩm hầu như không thừa nhận.
Rob Farley
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.