SQL查询改进

时间:2014-08-07 01:15:52

标签: mysql sql performance

我有这个查询需要20秒才能运行...

SELECT books.id, books.title, books.slug, books.source_id, books.thumb_url 
FROM books, book_cat 
WHERE books.id = book_cat.book_id AND book_cat.cat_id = 158 
ORDER BY books.id DESC LIMIT 50

book_catbookbook_cats

之间的联接表

book_cat = 158

cat_id中有39k行

有什么建议吗?

- 更新

所有PK,FK,索引(包括book_cat上的组合索引)都已到位。

BIGINT是的我知道,我期待很多书,很想改成INT。

UNIQUE键,它是PK的候选者

CREATE TABLE book_cat (
    book_id BIGINT UNSIGNED NOT NULL,
    cat_id SMALLINT UNSIGNED NOT NULL,
    UNIQUE(book_id, cat_id),
    CONSTRAINT FK_book_cat_1 FOREIGN KEY (book_id) REFERENCES books (id) ON DELETE CASCADE,
    CONSTRAINT FK_book_cat_2 FOREIGN KEY (cat_id) REFERENCES book_cats (id)
) ENGINE = INNODB;

3 个答案:

答案 0 :(得分:1)

在这种情况下,通常的罪魁祸首是没有具有适当值的索引。我会在book_cat上建议一个带有book_id和cat_id的索引。订单可能并不重要,但我首先使用的是更独特。

您可以尝试使用mySQL's EXPLAIN语句查看它将为您提供的信息。确保它使用预期的索引,或者创建一个索引,然后再试一次。

答案 1 :(得分:1)

首先,确保正确定义了表格。应将books.id定义为主键。索引应该存在于book_cat.book_idbook_cat.catid上,因为它们似乎是其他表的外键。

如果这样做,那么对于你正在处理的记录数量,下面的SQL应该非常快。

SELECT books.id, books.title, books.slug, books.source_id, books.thumb_url 
FROM books JOIN book_cat ON books.id = book_cat.book_id
WHERE book_cat.cat_id = 158 
ORDER BY books.id DESC LIMIT 50

答案 2 :(得分:1)

首先,我要使用表别名和正确的join语法重写您的查询:

SELECT b.id, b.title, b.slug, b.source_id, b.thumb_url 
FROM books JOIN
     book_cat bc
     ON b.id = bc.book_id
WHERE bc.cat_id = 158 
ORDER BY b.id DESC
LIMIT 50;

要优化此查询,请确保您在book_cat(book_id, cat_id)books(id)上有索引。以下等效版本的查询可能会产生最佳计划:

SELECT b.id, b.title, b.slug, b.source_id, b.thumb_url 
FROM books
WHERE EXISTS (SELECT 1 FROM book_cat bc WHERE b.id = bc.book_id AND bc.cat_id = 158)
ORDER BY b.id DESC
LIMIT 50;

此版本强调order by可以使用索引,搜索类别应使用索引。