如何从Doctrine QueryBuilder优化这个MySQL查询?

时间:2017-07-18 22:52:23

标签: mysql symfony doctrine-orm query-optimization entity-attribute-value

此查询由doctrine2 QueryBuilder生成(concat函数只需要2个参数),需要4秒。

SELECT  COUNT(*) AS dctrn_count
    FROM  
    (
        SELECT  DISTINCT id_4
            FROM  
            (
                SELECT  1 / LOCATE( ?, CONCAT( CONCAT( CONCAT(w0_.firstname, ' '),
                                                CONCAT(w0_.lastname, ' ') ), w1_.fullname ) 
                          ) AS sclr_0,
                        1 / LOCATE( ?, CONCAT( CONCAT( CONCAT(w0_.firstname, ' '),
                                                CONCAT(w0_.lastname, ' ') ), w1_.shortname ) 
                          ) AS sclr_1,
                        1 / LOCATE( ?, CONCAT( CONCAT( CONCAT(w0_.nickname, ' '),
                                                CONCAT(w0_.lastname, ' ') ), w1_.fullname ) 
                          ) AS sclr_2,
                        1 / LOCATE( ?, CONCAT( CONCAT( CONCAT(w0_.nickname, ' '),
                                                CONCAT(w0_.lastname, ' ') ), w1_.shortname ) 
                          ) AS sclr_3,
                        w0_.id AS id_4, w0_.slug AS slug_5, w0_.firstname AS firstname_6,
                        w0_.lastname AS lastname_7, w0_.nickname AS nickname_8,
                        w0_.gender AS gender_9, w0_.email AS email_10, w0_.email_checked AS email_checked_11,
                        w0_.title_en AS title_en_12, w0_.short_title AS short_title_13,
          -- lots of stuff removed (see edit) --
                        w5_.biography_en AS biography_en_55, w5_.created AS created_56, w5_.updated AS updated_57, w6_.id AS id_58, w6_.web_text AS web_text_59, w6_.created AS created_60
                    FROM  wmn_executive w0_
                    INNER JOIN  wmn_company w1_  ON w0_.company_id = w1_.id
                    INNER JOIN  wmn_industry w7_  ON w1_.industry_id = w7_.id
                    INNER JOIN  wmn_location w2_  ON w1_.location_id = w2_.id
                    INNER JOIN  wmn_country w3_  ON w2_.country_id = w3_.id
                    INNER JOIN  wmn_city w4_  ON w2_.city_id = w4_.id
                    LEFT JOIN  wmn_executive_link w5_  ON w0_.link_id = w5_.id
                    LEFT JOIN  wmn_web_executive w6_  ON w0_.id = w6_.executive_id
                    WHERE  w0_.original_id IS NULL
                      AND  w0_.user_id IS NOT NULL
                      AND  ( w0_.firstname LIKE ?
                              OR  w0_.lastname LIKE ?
                              OR  w0_.nickname LIKE ?
                              OR  w1_.fullname LIKE ?
                              OR  w1_.shortname LIKE ?
                              OR  w0_.title_en LIKE ?
                              OR  w0_.short_title LIKE ?
                              OR  w7_.industry_name_en LIKE ?
                              OR  w7_.industry_name_fr LIKE ?
                              OR  w3_.country_name_en LIKE ?
                              OR  w3_.country_name_fr LIKE ?
                              OR  w4_.city_name LIKE ? 
                          )
                    ORDER BY  sclr_0 DESC, sclr_1 DESC, sclr_2 DESC, sclr_3 DESC ) dctrn_result 
    ) dctrn_table

1 个答案:

答案 0 :(得分:0)

** ORDER BY对最终结果没有任何好处;删除它。

**

SELECT  COUNT(*) AS dctrn_count
    FROM  
    (
        SELECT  DISTINCT id_4

可以简化为

SELECT COUNT(DISTINCT(id_4))

** SELECT子句中的所有项都不使用,id_4除外;摆脱它们。

****这3个优化可能会将运行时间从4.0秒缩短到3.9秒。

然后你会说这不是真正的查询,而只是一个计数?

如果你打算像那样做一个凌乱的文本扫描,你需要在一个表中的所有这些字符串。更好的是,所有字符串在一个表中连接成一列。这只是用于搜索,而不是用于显示。然后在该列上创建一个FULLTEXT索引。这将解决ORLIKE '%...'问题。但是我不知道如何让它重新回到学说2中。