目前我在我的应用程序中遇到一些较慢的MySQL查询,我想加快速度。不幸的是,我不太确定哪种方法是正确的。
我有以下(虚构)表:Book
,Page
和Word
。
Word
是Page
的孩子word_page_id
Page
是Book
page_book id
的孩子
我已经在page_book_id
,word_page_id
,book_user_id
和book_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)
如何加快此类查询? 是否涉及额外的索引?
答案 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