PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Tối ưu hóa nhiều kết hợp

Luôn có 2 điều cần xem xét khi tối ưu hóa các truy vấn:

  • Những chỉ mục nào có thể được sử dụng (bạn có thể cần tạo chỉ mục)
  • Cách truy vấn được viết (bạn có thể cần thay đổi truy vấn để cho phép người chọn truy vấn có thể tìm thấy các chỉ mục thích hợp và không đọc lại dữ liệu một cách dư thừa)

Một vài nhận xét:

  • Bạn đang thực hiện thao tác ngày tháng trước khi bạn tham gia các cuộc hẹn hò của mình. Theo nguyên tắc chung, điều này sẽ ngăn người chọn truy vấn sử dụng chỉ mục ngay cả khi nó tồn tại. Bạn nên cố gắng viết biểu thức của mình theo cách mà các cột được lập chỉ mục tồn tại không thay đổi ở một bên của biểu thức.

  • Các truy vấn con của bạn đang lọc theo cùng một phạm vi ngày với generate_series . Đây là một sự trùng lặp và nó hạn chế khả năng của nạn nhân trong việc chọn cách tối ưu hóa hiệu quả nhất. Tôi nghi ngờ rằng điều đó có thể đã được viết vào để cải thiện hiệu suất vì optimser không thể sử dụng chỉ mục trên cột ngày (body_time )?

  • LƯU Ý :Chúng tôi thực sự rất muốn sử dụng một chỉ mục trên Body.body_time

  • ORDER BY trong các truy vấn con là tốt nhất là dư thừa. Tệ nhất là nó có thể buộc trình tối ưu hóa truy vấn sắp xếp tập hợp kết quả trước khi tham gia; và điều đó không nhất thiết là tốt cho kế hoạch truy vấn. Thay vì chỉ áp dụng đặt hàng ngay ở phần cuối để hiển thị cuối cùng.

  • Sử dụng LEFT JOIN trong truy vấn phụ của bạn là không phù hợp. Giả sử bạn đang sử dụng quy ước ANSI cho NULL hành vi (và bạn nên như vậy), bất kỳ bên ngoài tham gia vào envelope sẽ trả về envelope_command=NULL và do đó, những điều này sẽ bị loại trừ bởi điều kiện envelope_command=? .

  • Truy vấn con oi gần như giống hệt nhau được lưu cho envelope_command giá trị. Điều này buộc người sử dụng phải quét các bảng bên dưới giống nhau hai lần. Bạn có thể sử dụng bảng tổng hợp kỹ thuật nối với dữ liệu một lần và chia các giá trị thành 2 cột.

Hãy thử cách sau sử dụng kỹ thuật xoay:

SELECT  p.period,
        /*The pivot technique in action...*/
        SUM(
        CASE WHEN envelope_command = 1 THEN body_size
        ELSE 0
        END) AS Outbound,
        SUM(
        CASE WHEN envelope_command = 2 THEN body_size
        ELSE 0
        END) AS Inbound
FROM    (
        SELECT  date '2009-10-01' + s.day AS period
        FROM    generate_series(0, date '2009-10-31' - date '2009-10-01') AS s(day)
        ) AS p 
        /*The left JOIN is justified to ensure ALL generated dates are returned
          Also: it joins to a subquery, else the JOIN to envelope _could_ exclude some generated dates*/
        LEFT OUTER JOIN (
        SELECT  b.body_size,
                b.body_time,
                e.envelope_command
        FROM    body AS b 
                INNER JOIN envelope e 
                  ON e.message_id = b.message_id 
        WHERE   envelope_command IN (1, 2)
        ) d
          /*The expressions below allow the optimser to use an index on body_time if 
            the statistics indicate it would be beneficial*/
          ON d.body_time >= p.period
         AND d.body_time < p.period + INTERVAL '1 DAY'
GROUP BY p.Period
ORDER BY p.Period

CHỈNH SỬA :Đã thêm bộ lọc do Tom H.

đề xuất

  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Viết truy vấn cho nhiều bảng trong php

  2. PostgreSQL tạo bảng nếu không tồn tại

  3. Hệ điều hành Android và postgreSQL

  4. Heroku không di chuyển mô hình trong Django

  5. Tại sao giao dịch PostgreSQL này đưa ra CẢNH BÁO:không có giao dịch nào đang diễn ra