【问题标题】:Huge SQL Statement Optimization巨大的 SQL 语句优化
【发布时间】:2015-04-27 13:10:58
【问题描述】:

以下语句每个查询运行 11 到 12 秒。我试图添加索引和其他东西,但现在我不知道下一步该做什么。

这是 codeigniter 中的“搜索”。

   SELECT produktlisten.id as id,
          produktlisten.name as name,
          produktlisten.alias,
          users_company.name as company_name,
          produkte.id as produkte_id,
          produkte.name as produkte_name,
          sliderpic,
          produktlisten.description as description,
           MATCH (produktlisten.name,
                  produktlisten.description,
                  produktlisten.tags) AGAINST ('<<SEARCH TERM>>' )
          + MATCH (users_company.name,
                   users_company.description) AGAINST ('<<SEARCH TERM>>' )
          + MATCH (produkte.name,
                   produkte.description,
                   produkte.tags) AGAINST ('<<SEARCH TERM>>' ) AS relevanz
     FROM produktlisten
LEFT JOIN produkte ON produktlisten.id = produkte.produktlisten_id
      AND produkte.active = 1
LEFT JOIN stilrichtung ON produktlisten.stil_id = stilrichtung.id
LEFT JOIN users_company ON produktlisten.company_id = users_company.id
    WHERE produktlisten.active =  '1'
      AND (MATCH (produktlisten.name,
                  produktlisten.description,
                  produktlisten.tags) AGAINST ('<<SEARCH TERM>>')
           OR MATCH (produkte.name,
                     produkte.description,
                     produkte.tags) AGAINST ('<<SEARCH TERM>>')
           OR MATCH (users_company.name,
                     users_company.description) AGAINST ('<<SEARCH TERM>>' ))
 GROUP BY id
 ORDER BY relevanz DESC
 LIMIT 21   

数据库很大,表也很大,每个 5-15 MB。

感谢您的帮助!

【问题讨论】:

  • 所有这些匹配看起来会让你头疼。是否可以在 PHP 中运行单独的查询并与各种响应相交?
  • 请为每个表提供 SHOW CREATE TABLE 并为查询提供 EXPLAIN SELECT。
  • 什么版本的 MySQL?我想到的解决方案将需要 5.6。并且这些表需要是 ENGINE=InnoDB;是吗?
  • 尝试对MATCH 表达式进行基准测试。您可以通过将它们完全从查询中删除并从包含它们时获得的结果中减去新结果来做到这一点。此外,如果它们很昂贵,请考虑只使用一个匹配表达式(而不是六个)。我知道它可能超出了范围,但它看起来像是更适合 solr 或 elasticsearch 的工作。

标签: mysql sql codeigniter query-optimization


【解决方案1】:

我想给你一些提示,因为我不是 MySQL 人。如果有什么工作会很好。

    SELECT produktlisten.id as id,
          produktlisten.name as name,
          produktlisten.alias,
          users_company.name as company_name,
          produkte.id as produkte_id,
          produkte.name as produkte_name,
          sliderpic,
          produktlisten.description as description,
           MATCH (produktlisten.name,
                  produktlisten.description,
                  produktlisten.tags) AGAINST ('<<SEARCH TERM>>' )
          + MATCH (users_company.name,
                   users_company.description) AGAINST ('<<SEARCH TERM>>' )
          + MATCH (produkte.name,
                   produkte.description,
                   produkte.tags) AGAINST ('<<SEARCH TERM>>' ) AS relevanz
     FROM produktlisten
LEFT JOIN produkte ON produktlisten.id = produkte.produktlisten_id 
LEFT JOIN stilrichtung ON produktlisten.stil_id = stilrichtung.id
LEFT JOIN users_company ON produktlisten.company_id = users_company.id
    WHERE produktlisten.active =  '1' AND produkte.active = 1
      AND (MATCH (produktlisten.name,
                  produktlisten.description,
                  produktlisten.tags) AGAINST ('<<SEARCH TERM>>')
           OR MATCH (produkte.name,
                     produkte.description,
                     produkte.tags) AGAINST ('<<SEARCH TERM>>')
           OR MATCH (users_company.name,
                     users_company.description) AGAINST ('<<SEARCH TERM>>' ))
 GROUP BY id
 ORDER BY relevanz DESC
 LIMIT 21   

或者如果它来自 SQL Server,那么我会尝试使用子查询来限制行数以获得更好的性能。

               SELECT produktlisten.id as id,
          produktlisten.name as name,
          produktlisten.alias,
          users_company.name as company_name,
          produkte.id as produkte_id,
          produkte.name as produkte_name,
          sliderpic,
          produktlisten.description as description,
           MATCH (produktlisten.name,
                  produktlisten.description,
                  produktlisten.tags) AGAINST ('<<SEARCH TERM>>' )
          + MATCH (users_company.name,
                   users_company.description) AGAINST ('<<SEARCH TERM>>' )
          + MATCH (produkte.name,
                   produkte.description,
                   produkte.tags) AGAINST ('<<SEARCH TERM>>' ) AS relevanz
     FROM  
     (
     Select * from produktlisten where active = '1'
      AND (MATCH (produktlisten.name,
                  produktlisten.description,
                  produktlisten.tags) AGAINST ('<<SEARCH TERM>>')
           OR MATCH (produkte.name,
                     produkte.description,
                     produkte.tags) AGAINST ('<<SEARCH TERM>>')
           OR MATCH (users_company.name,
                     users_company.description) AGAINST ('<<SEARCH TERM>>' ))    
     ) produktlisten
LEFT JOIN produkte ON produktlisten.id = produkte.produktlisten_id AND produkte.active = 1
LEFT JOIN stilrichtung ON produktlisten.stil_id = stilrichtung.id
LEFT JOIN users_company ON produktlisten.company_id = users_company.id
 GROUP BY id
 ORDER BY relevanz DESC
 LIMIT 21   

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-10
    • 1970-01-01
    • 2013-03-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多