计数项目的查询速度慢

时间:2018-02-11 20:54:05

标签: mysql

我有一个包含过滤器的列表,我必须计算每个过滤器中有多少项,但是当设置了多个过滤器时,以下查询会变慢并且速度会慢得多

SELECT COUNT(*) FROM (
    SELECT itf.`filter_id`
    FROM `item_to_filter` AS `itf`
    JOIN `item_to_inventory` AS `iti` ON (itf.`item_id` = iti.`item_id` AND iti.`quantity` > 0)
    WHERE 1 = 1
    AND (
        (itf.`filter_group_id` = 2 AND itf.`filter_id` IN (1))
        OR (itf.`filter_group_id` = 4 AND itf.`filter_id` IN (55)) //gets slower
        OR (itf.`filter_group_id` = 1 AND itf.`filter_id` IN (107, 108)) //gets much slower
    )
    GROUP BY itf.`item_id`
    HAVING COUNT(DISTINCT itf.`filter_group_id`) = 3
) AS `total_items`

还有其他方法可以编写查询来计算每个过滤器中的项目

在这里你可以看到表结构和数据(索引是否正确设置?)

enter image description here enter image description here

1 个答案:

答案 0 :(得分:1)

尝试这一个:将条件包装到UNION ALL子查询中。然后加入你的桌子。

SELECT COUNT(*) FROM (
    SELECT itf.filter_id
    FROM (
        SELECT 2 as filter_group_id 1   as filter_id UNION ALL
        SELECT 4 as filter_group_id 55  as filter_id UNION ALL
        SELECT 1 as filter_group_id 107 as filter_id UNION ALL
        SELECT 1 as filter_group_id 108 as filter_id
    ) f -- filters
    JOIN item_to_filter AS itf USING(filter_group_id, filter_id)
    JOIN item_to_inventory AS iti ON itf.item_id = iti.item_id
    WHERE iti.quantity > 0
    GROUP BY itf.item_id
    HAVING COUNT(DISTINCT itf.filter_group_id) = 3
) AS total_items

您应该在item_to_filter(filter_group_id, filter_id)上定义索引。但正如我在评论中写的那样,如果存在该索引,引擎可能会进行相同的优化。

为了更好地利用给定的索引,您可以将查询重写为

SELECT COUNT(*) FROM (
    SELECT item_id
    FROM item_to_inventory AS iti
    JOIN item_to_filter AS itf2 USING(item_id) -- itf2: group_id = 2
    JOIN item_to_filter AS itf4 USING(item_id) -- itf4: group_id = 4
    JOIN item_to_filter AS itf1 USING(item_id) -- itf1: group_id = 1
    WHERE iti.quantity > 0
      AND itf2.filter_group_id = 2 AND itf2.filter_id IN (1)
      AND itf4.filter_group_id = 4 AND itf4.filter_id IN (55)
      AND itf1.filter_group_id = 1 AND itf1.filter_id IN (107,108)
) AS total_items

但即使在这里item_to_filter(filter_group_id, filter_id)上的索引也应该提高效果。