2015-10-06 47 views
1

有没有办法来优化这个查询。它需要超过40秒的时间来执行。我尝试了很多方式来创建索引。这种做法很少帮助,但是查询时间太长。如何优化这个sql查询(内连接)

SELECT b.id, 
    Count(DISTINCT a.id, c.chapters_id) AS pct, 
    Count(DISTINCT e.id)     AS eCount, 
    Count(DISTINCT f.id)     AS fCount, 
    Count(DISTINCT d2.id)     AS d2Count, 
    b.NAME, 
    e.NAME, 
    e.address2, 
    f.NAME, 
    d2.is_active 
FROM tableA a 
     INNER JOIN tableB b 
       ON a.modules_id = b.id 
     INNER JOIN tableC c 
       ON a.modules_id = c.modules_id 
     INNER JOIN tableD d1 
       ON d1.id = b.store_users_id 
     INNER JOIN tableD d2 
       ON d2.id = a.store_users_id 
     INNER JOIN tableE e 
       ON e.id = d2.stores_id 
     INNER JOIN tableF f 
       ON e.city = f.id 
WHERE b.type IN(1, 2, 4) 
     AND b.organizations_id = 156 
     AND b.is_enable = true 
GROUP BY b.NAME,b.id 

EXPLAIN

+----+-------------+-------+--------+-----------------------------------------------------------------------------------------------------+-----------------------------+---------+--------------------------+------+---------------------------------------+ 
| id | select_type | table | type | possible_keys                      | key       | key_len | ref      | rows | Extra         | 
+----+-------------+-------+--------+-----------------------------------------------------------------------------------------------------+-----------------------------+---------+--------------------------+------+---------------------------------------+ 
| 1 | SIMPLE  | b  | range | PRIMARY,fk_modules_organizations1,fk_modules_store_users1,sort_modules_name,wh_modules_type,new_idx | new_idx      | 9  | NULL      | 160 | Using index condition; Using filesort | 
| 1 | SIMPLE  | c  | ref | fk_module_chapters_modules1                   | fk_module_chapters_modules1 | 4  |   b.id    | 1 | NULL         | 
| 1 | SIMPLE  | d1 | eq_ref | PRIMARY                        | PRIMARY      | 4  |   b.store_users_id | 1 | Using index       | 
| 1 | SIMPLE  | a  | ref | store_users_id_UNIQUE,fk_user_modules_store_users1,fk_user_modules_modules1       | fk_user_modules_modules1 | 4  |   b.id    | 149 | NULL         | 
| 1 | SIMPLE  | d2 | eq_ref | PRIMARY,fk_store_users_stores1                  | PRIMARY      | 4  |   a.store_users_id | 1 | NULL         | 
| 1 | SIMPLE  | e  | eq_ref | PRIMARY,Stores-Cities                    | PRIMARY      | 4  |  d2.stores_id  | 1 | Using where       | 
| 1 | SIMPLE  | f  | eq_ref | PRIMARY                        | PRIMARY      | 4  |   e.city   | 1 | NULL         | 
+----+-------------+-------+--------+-----------------------------------------------------------------------------------------------------+-----------------------------+---------+--------------------------+------+---------------------------------------+ 
+0

更换请提供'SHOW为您的表TABLE语句tablename'。这将帮助我们识别任何不正确的数据类型,并查看您拥有的索引。此外,“IN”总是只有3个值,还是有所不同?这些价值从何而来? (即用户输入,或以前运行的查询等) –

+0

嗨,感谢您查看我的查询。 IN总是只有3个值(1,2,4)。 SHOW CREATE TABLE 5个表的详细信息非常大。请告诉我你是否需要为任何特定的表创建表。 thnks – darkrace

+0

您没有收到任何回复,因为您没有提供明确的信息。提供所有SHOW CREATE TABLE语句,除非您的雇主或类似人员禁止您这样做,否则更正您的查询以显示实际的表名和列名,而不是这些假名称。它有助于我们的理解,并降低编辑名称时出错的风险。无论如何,我们可以从'* _id'列和EXPLAIN语句中的键中推断出大部分名称。 –

回答

0

这可能会帮助一些:

INDEX(organizations_id, is_enable, type) -- on b 

既然你说COUNT(DISTINCT...),它闻起来像JOINs呈爆炸式增长的行数,那么你DISTINCTifying他们回来到他们应该去的地方。一种方法看到SELECT COUNT(*) FROM ... JOIN ...没有最后的GROUP BY。如果这是一个比任何表大小都大的数字,那么你就有这个经典问题。

有时候解决方案是一个JOIN通过

SELECT ..., 
     (SELECT COUNT(*) FROM x ...) AS x_ct, -- instead of `JOIN x` 
     ...