mysql - 如何优化大表上的计数 SQL 查询

标签 mysql sql query-optimization

我在 mysql (innodb) 上有一个大表,其中包含产品 Assets (1300 万行)。这是我的数据库的一些模式:

product <-many2one-- file_item --one2many--> family --many2one--> download_type

*file_item* 表是具有数百万行的大表。我尝试使用以下 sql 查询按下载类型计算产品:

select t.name as type, 
count(p.product_id) as n 
from file_item p 
inner join family f on f.id = p.family_id 
inner join type t on f.id_type = t.id 
group by t.id order by t.name;

*file_item* 表有 3 个索引:

  • product_family_idx(product_id,family_id)
  • family_idx (family_id)
  • product_idx (product_id) 解释输出:
+----+-------------+-------+--------+-----------------------------------+---------+---------+-------------------+----------+---------------------------------+
| id | select_type | table | type   | possible_keys                     | key     | key_len | ref               | rows     | Extra                           |
+----+-------------+-------+--------+-----------------------------------+---------+---------+-------------------+----------+---------------------------------+
|  1 | SIMPLE      | p     | ALL    | FAMILY_IDX,PRODUCT_FAMILY_IDX     | NULL    | NULL    | NULL              | 13862870 | Using temporary; Using filesort | 
|  1 | SIMPLE      | f     | eq_ref | PRIMARY,TYPE_ID                   | PRIMARY | 4       | MEDIA.p.FAMILY_IDX|        1 |                                 | 
|  1 | SIMPLE      | t     | eq_ref | PRIMARY                           | PRIMARY | 4       | MEDIA.f.TYPE_ID   |        1 |                                 | 
+----+-------------+-------+--------+-----------------------------------+---------+---------+-------------------+----------+---------------------------------+

查询需要1个多小时才能返回结果。 请问我该如何优化查询?!

最佳答案

这是您的原始查询:

select t.name as type,  
count(p.product_id) as n  
from file_item p  
inner join family f on f.id = p.family_id  
inner join type t on f.id_type = t.id  
group by t.id order by t.name; 

您需要进行两项主要更改:

主要变化#1:重构查询

SELECT A.ProductCount,B.name type
FROM
(
    SELECT id_type id,COUNT(1) ProductCount
    FROM
    (
        SELECT p.id_type
        FROM (SELECT family_id,id_type FROM file_item) p
        INNER JOIN (SELECT id FROM family) f on f.id = p.family_id
    ) AA
    GROUP BY id_type
) A
INNER JOIN type B USING (id)
ORDER BY B.name;

主要变化#2:创建支持重构查询的索引

ALTER TABLE file_item ADD INDEX family_type_idx (family_id,id_type);

试一试!!!

关于mysql - 如何优化大表上的计数 SQL 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7178849/

相关文章:

mysql - 触发错误1064

mysql - 使用mysql工作台创建数据库

mysql - 检查上次查询是否使用了缓冲区

performance - 如何优化在 postgresql 中查询此数据?

mysql - 在 EXISTS 查询中使用 LIMIT 有什么意义吗?

mysql - 什么类型的索引最适合此查询?

php - Prepared statements : while loop inside while loop. 如何分组显示有序文件?

java - 尽管将SQL数据库链接到我的JavaFx程序但仍尝试登录却抛出错误

java - Springboot findBy List <String> hibernate @Query

sql - 将字符串转换为 SSIS 包中的十进制值