0

我正在为图书馆的搜索框编写一个自动建议,它非常慢。有没有在线工具或者愿意帮我优化的人?

 SELECT *,
       grbc_books.id book_id
FROM   grbc_books
       LEFT JOIN grbc_series
              ON grbc_books.series_id = grbc_series.id
       JOIN grbc_collections
         ON grbc_books.collection_id = grbc_collections.id
       LEFT JOIN grbc_places
              ON grbc_books.place_id = grbc_places.id
       RIGHT JOIN grbc_books_subjects
               ON grbc_books_subjects.book_id = grbc_books.id
       LEFT JOIN grbc_subjects
              ON grbc_books_subjects.subject_id = grbc_subjects.id
       RIGHT JOIN grbc_books_authors
               ON grbc_books_authors.book_id = grbc_books.id
       LEFT JOIN grbc_authors
              ON grbc_books_authors.author_id = grbc_authors.id
                 AND ( ( title LIKE "%yea%" )
                        OR ( subtitle LIKE "%yea%" )
                        OR ( series LIKE "%yea%" )
                        OR ( `subject` LIKE "%yea%" )
                        OR ( `first` LIKE "%yea%" )
                        OR ( `last` LIKE "%yea%" )
                        OR ( place LIKE "%yea%" ) )
GROUP  BY `title`,
          subtitle
ORDER  BY title
LIMIT  10;  

提前致谢。

4

5 回答 5

1

将“*”替换为您真正需要的列...现在您将获得所有表的所有列!

于 2013-03-07T11:17:08.003 回答
1

这里的主要放缓将是LIKE '%yea%'条件。(另外——它们不应该在一个WHERE子句中,而不是最后一个LEFT JOIN ... ON...子句中吗?)这种查询的问题是 MySQL 不能使用任何索引来查找必要的行。每次都需要进行全面扫描。正确的解决方案是使用全文索引

此外,正如Oli 建议的那样,删除*可能会有所帮助。

于 2013-03-07T11:21:00.590 回答
1

正如其他人提到的那样,LIKE 可能是您的瓶颈。我的建议是让你开始使用 MATCH AGAINST 而不是 like。 http://dev.mysql.com/doc/refman/5.5/en//fulltext-search.html

于 2013-03-07T11:26:18.147 回答
1

请注意,“%yea%”不能使用索引,因此效率低下,但“yea%”可以,因此速度更快。

请记住,如果有可能其中没有关联的数据,您只需要外部连接一个表。我不知道您的数据结构,但对于像主题和作者这样的表,这似乎不太可能。

如果我正在编写这个查询,而不是切换到使用 FULLTEXT,那么我希望它看起来像这样......

 SELECT DISTINCT b.title
               , b.subtitle
               , b.id book_id
   FROM grbc_books b
   JOIN grbc_collections c
     ON c.id = b.collection_id
   JOIN grbc_books_subjects bh
     ON bh.book_id = b.id
   JOIN grbc_subjects h
     ON h.id = bh.subject_id 
   JOIN grbc_books_authors ba  
     ON ba.book_id = b.id
   JOIN grbc_authors a
     ON a.id = ba.author_id 
   LEFT 
   JOIN grbc_series s
     ON s.id = b.series_id
    AND s.series  LIKE "%yea%" 
   LEFT 
   JOIN grbc_places p
     ON p.id = b.place_id 
    AND p.place   LIKE "%yea%" 
  WHERE b.title LIKE "%yea%" 
     OR b.subtitle LIKE "%yea%" 
     OR h.subject LIKE "%yea%" 
     OR a.first LIKE "%yea%" 
     OR a.last LIKE "%yea%" 
  ORDER  
     BY b.title
  LIMIT 10;  

...但是我的猜测是,这只会对性能产生很小的影响。

于 2013-03-07T11:35:16.027 回答
1

通过从等式中删除数据库来“优化”全文搜索。您的选择是:

  • 索尔
  • 弹性搜索
  • 狮身人面像

当涉及到全文搜索时,关系数据库非常慢,您对此无能为力。如果您预计流量较小并且您可以接受缓慢,请尝试将索引添加到您的文本字段。它会使 INSERT 语句与数据量成比例地变慢。

最后,您可以通过在语句之前添加“EXPLAIN”来解决您的查询:

EXPLAIN SELECT *,
       grbc_books.id book_id
FROM   grbc_books
       LEFT JOIN grbc_series
              ON grbc_books.series_id = grbc_series.id
       JOIN grbc_collections
         ON grbc_books.collection_id = grbc_collections.id
       LEFT JOIN grbc_places
              ON grbc_books.place_id = grbc_places.id
       RIGHT JOIN grbc_books_subjects
               ON grbc_books_subjects.book_id = grbc_books.id
       LEFT JOIN grbc_subjects
              ON grbc_books_subjects.subject_id = grbc_subjects.id
       RIGHT JOIN grbc_books_authors
               ON grbc_books_authors.book_id = grbc_books.id
       LEFT JOIN grbc_authors
              ON grbc_books_authors.author_id = grbc_authors.id
                 AND ( ( title LIKE "%yea%" )
                        OR ( subtitle LIKE "%yea%" )
                        OR ( series LIKE "%yea%" )
                        OR ( `subject` LIKE "%yea%" )
                        OR ( `first` LIKE "%yea%" )
                        OR ( `last` LIKE "%yea%" )
                        OR ( place LIKE "%yea%" ) )
GROUP  BY `title`,
          subtitle
ORDER  BY title

如果您决定继续使用数据库方法,请考虑缓存以不重复查询。

于 2013-03-07T11:35:27.610 回答