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

nó có thể được thực thi nhanh hơn với lượng lớn dữ liệu không [MySQL]

Nhìn vào EXPLAIN của bạn đầu ra, tôi lo ngại rằng việc bạn sử dụng các truy vấn con đã dẫn đến việc sử dụng các chỉ mục dưới mức tối ưu. Tôi cảm thấy (mà không có bất kỳ sự biện minh nào - và về điều này, tôi rất có thể đã sai) viết lại bằng cách sử dụng JOIN có thể dẫn đến một truy vấn được tối ưu hóa hơn.

Để làm được điều đó, chúng tôi cần hiểu truy vấn của bạn dự định làm gì. Sẽ rất hữu ích nếu câu hỏi của bạn đã trình bày rõ ràng nó, nhưng sau một hồi đắn đo, tôi quyết định rằng truy vấn của bạn đang cố gắng tìm nạp danh sách tất cả các từ khóa khác xuất hiện trong bất kỳ bài viết nào có chứa một số từ khóa nhất định, cùng với một số của tất cả các bài viết có các từ khóa đó xuất hiện .

Bây giờ, hãy xây dựng lại truy vấn theo các giai đoạn:

  1. Tìm nạp " bất kỳ bài viết nào có chứa một số từ khóa nhất định "(không lo trùng lặp):

    SELECT ca2.article_id
    FROM
           career_article_keyword AS ca2
    WHERE
          ca2.keyword_id = 9;
    
  2. Tìm nạp " tất cả các từ khóa khác xuất hiện trong [ở trên] "

    SELECT ca1.keyword_id
    FROM
           career_article_keyword AS ca1
      JOIN career_article_keyword AS ca2 ON (ca2.article_id = ca1.article_id)
    WHERE
          ca1.keyword_id <> 9
      AND ca2.keyword_id =  9
    GROUP BY ca1.keyword_id;
    
  3. Tìm nạp " [phần trên], cùng với tổng số tất cả các bài viết có các từ khóa đó xuất hiện "

    SELECT ca1.keyword_id, COUNT(DISTINCT ca0.article_id) AS cnt
    FROM
           career_article_keyword AS ca0
      JOIN career_article_keyword AS ca1 USING (keyword_id)
      JOIN career_article_keyword AS ca2 ON (ca2.article_id = ca1.article_id)
    WHERE
          ca1.keyword_id <> 9
      AND ca2.keyword_id =  9
    GROUP BY ca1.keyword_id
    ORDER BY cnt DESC;
    
  4. Cuối cùng, chúng tôi muốn thêm vào đầu ra chính từ khóa phù hợp từ career_keyword bảng:

    SELECT ck.keyword_id, ck.keyword, COUNT(DISTINCT ca0.article_id) AS cnt
    FROM
           career_keywords        AS ck 
      JOIN career_article_keyword AS ca0 USING (keyword_id)
      JOIN career_article_keyword AS ca1 USING (keyword_id)
      JOIN career_article_keyword AS ca2 ON (ca2.article_id = ca1.article_id)
    WHERE
          ca1.keyword_id <> 9
      AND ca2.keyword_id =  9
    GROUP BY ck.keyword_id -- equal to ca1.keyword_id due to join conditions
    ORDER BY cnt DESC;
    

Một điều rõ ràng ngay lập tức là truy vấn ban đầu của bạn đã tham chiếu đến career_keywords hai lần, trong khi truy vấn được viết lại này chỉ tham chiếu đến bảng đó một lần; điều này chỉ có thể giải thích sự khác biệt về hiệu suất - hãy thử xóa tham chiếu thứ hai đến nó (tức là nơi nó xuất hiện trong truy vấn con đầu tiên của bạn), vì nó hoàn toàn dư thừa ở đó.

Nhìn lại truy vấn này, chúng ta có thể thấy rằng các phép nối đang được thực hiện trên các cột sau:

  • career_keywords.keyword_id trong ck JOIN ca0

    Bảng này xác định PRIMARY KEY (`keyword_id`) , do đó, có một chỉ mục tốt có thể được sử dụng cho kết hợp này.

  • career_article_keyword.article_id trong ca1 JOIN ca2

    Bảng này xác định UNIQUE KEY `article_id` (`article_id`,`keyword_id`) và, kể từ article_id là cột ngoài cùng bên trái trong chỉ mục này, có một chỉ mục tốt có thể được sử dụng cho kết hợp này.

  • career_article_keyword.keyword_id trong ck JOIN ca0ca0 JOIN ca1

    Không có chỉ mục nào có thể được sử dụng cho kết hợp này:chỉ mục duy nhất được xác định trong bảng này có một cột khác, article_id ở bên trái của keyword_id - vì vậy MySQL không thể tìm thấy keyword_id các mục trong chỉ mục mà không biết article_id trước . Tôi khuyên bạn nên tạo một chỉ mục mới có keyword_id là cột ngoài cùng bên trái của nó.

    (Nhu cầu về chỉ mục này có thể đã được xác định một cách bình đẳng trực tiếp từ việc xem xét truy vấn ban đầu của bạn, nơi hai truy vấn ngoài cùng của bạn thực hiện các phép nối trên cộ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. Có sử dụng SET NAMES không

  2. SQL - Chỉ nhận kết quả của năm hiện tại

  3. CHÈN hoặc CẬP NHẬT hàng loạt MySQL

  4. Cấp đặc quyền đã chọn cho các hàng có điều kiện

  5. chuỗi kết nối trở lại bảng mục tiêu