SQL查询速度有两个内连接和concat

时间:2011-03-15 12:33:29

标签: mysql group-by performance inner-join

我有三张桌子:

  • 书籍;
  • 作者;
  • list_items(包含纽约时报的畅销书清单)

我使用此查询来获取一位作者,该作者的书籍在畅销书列表中保留了最长的周数:

SELECT authors.full_name, COUNT(*) FROM authors
 INNER JOIN books ON books.author LIKE CONCAT('%', authors.full_name, '%')
 INNER JOIN list_items ON list_items.book_title = books.title
 GROUP BY authors.full_name ORDER BY count(*) DESC LIMIT 1

此查询大约需要6分钟,而没有第二个JOIN的类似查询则需要不到一秒钟。如何优化我的查询?
更新 EXPLAIN就是这样:

table      type   possible_keys key      key_len ref         rows   Extra
authors    ALL    <NULL>        <NULL>   <NULL>  <NULL>      2555   Using temporary; Using filesort
list_items ALL    book_name     <NULL>   <NULL>  <NULL>   31040  Using join buffer
books      eq_ref PRIMARY      PRIMARY  767     list_items. 1      Using where
                                                book_title

2 个答案:

答案 0 :(得分:1)

我认为你不需要使用额外的subselect语句。我采用了你更快的语句并删除了内部的select语句。不知道这会影响执行时间,但它有点清洁,imho。

SELECT COUNT(*), authors.full_name
FROM list_items
INNER JOIN books ON books.title = list_items.title
INNER JOIN relations ON books.id = relations.book_id
INNER JOIN authors ON authors_id = relations.author_id
GROUP BY authors.full_name
ORDER BY COUNT(*);

答案 1 :(得分:0)

最终,我通过重组数据库方案解决了这个问题。

根问题在字段books.author中可能包含多个作者名称,因此在初始查询中包含CONCAT。我添加了一个新表来应用多对多关系,其中authors.idbooks.id已关联。

然后我使用了这个查询:

SELECT COUNT (*), items.full_name
    FROM list_items
         INNER JOIN
         (SELECT books.title, authors.full_name
            FROM books INNER JOIN relations ON books.ID = relations.book_id
                 INNER JOIN authors ON authors.ID = relations.author_id
                 ) items ON items.title = list_items.book_title
GROUP BY items.full_name
ORDER BY COUNT (*) DESC;

执行时间降至0.4秒。