如何通过索引加速左连接查询?

时间:2015-07-01 14:24:41

标签: mysql indexing

目前我在我的应用程序中遇到一些较慢的MySQL查询,我想加快速度。不幸的是,我不太确定哪种方法是正确的。

我有以下(虚构)表:BookPageWord
WordPage的孩子word_page_id PageBook

page_book id的孩子

我已经在page_book_idword_page_idbook_user_idbook_flag_delete上设置了单独的索引。

SELECT `book`.*, COUNT(word_id) AS `word_amount` FROM `book` 
LEFT JOIN `page` ON page_book_id = book_id 
LEFT JOIN `word` ON word_page_id = paragraph_id 
WHERE (book_user_id = 1) AND (book_flag_delete IS NULL) 
GROUP BY `book_id` 
ORDER BY `book_id` ASC LIMIT 100

SELECT COUNT(DISTINCT `book_id`) AS `book_row_count` FROM `book` 
LEFT JOIN `page` ON page_book_id = book_id 
LEFT JOIN `word` ON word_page_id = page_id 
WHERE (book_user_id = 59) AND (book_flag_delete IS NULL)

如何加快此类查询? 是否涉及额外的索引?

4 个答案:

答案 0 :(得分:1)

对于此查询:

SELECT b.*, COUNT(w.word_id) AS `word_amount`
FROM `book` b LEFT JOIN
     `page` p
     ON p.page_book_id = b.book_id LEFT JOIN
     `word` w
     ON w.word_page_id = p.paragraph_id 
WHERE (b.book_user_id = 1) AND (b.book_flag_delete IS NULL) 
GROUP BY b.`book_id` 
ORDER BY b.`book_id` ASC
LIMIT 100;

最佳索引包括:book(user_id, book_flag_delete, book_id)page(page_book_id, paragraph_id)word(word_page_id, word_id)

然而,总体来说可能很贵。您可以尝试将查询编写为:

SELECT b.*,
       (SELECT COUNT(w.word_id) 
        FROM `page` p JOIN
             `word` w
             ON w.word_page_id = p.paragraph_id 
        WHERE p.page_book_id = b.book_id
       ) AS `word_amount`
FROM `book` b LEFT JOIN         
WHERE (b.book_user_id = 1) AND (b.book_flag_delete IS NULL) 
ORDER BY b.`book_id` ASC
LIMIT 100;

相同的索引索引在这里工作。但是,此查询应该避免一次性所有数据组(相反,它使用聚合的索引)。

答案 1 :(得分:1)

多对多映射表的最佳模式是

CREATE TABLE XtoY (
    # No surrogate id for this table
    x_id MEDIUMINT UNSIGNED NOT NULL,   -- For JOINing to one table
    y_id MEDIUMINT UNSIGNED NOT NULL,   -- For JOINing to the other table
    # Include other fields specific to the 'relation'
    PRIMARY KEY(x_id, y_id),            -- When starting with X
    INDEX      (y_id, x_id)             -- When starting with Y
) ENGINE=InnoDB;

详情'为什么'在my index cookbook

答案 2 :(得分:1)

在您用于加入的字段上设置索引。

进一步确保它们具有相同的数据类型,编码和排序规则,否则也不会使用索引。

mysql> EXPLAIN <query>将显示实际使用的字段(输出中的key列)和可用的索引(possible_keys输出字段)。

答案 3 :(得分:-2)

在您的选择中,您将要避免使用通配符“*”来抓取列。加上使用别名总是!!这将使您的数据库不必创建“虚拟”别名。

select book1.column1, book1.column2, page1.column1 
from book book1 
left join page page1 
on page1.page_book_id = book1.book_id
..... blah