group by减慢了查询速度

时间:2012-12-22 16:49:38

标签: mysql sql

我在产品表上有以下索引:(product_t,productid,forsale)。 MySQL手册说:

GROUP BY只列出构成索引最左边前缀而不包含其他列的列。 http://dev.mysql.com/doc/refman/5.0/en/group-by-optimization.html

当我执行以下查询时

SELECT z.product_t, COUNT(z.productid)
FROM xcart_products z
JOIN xcart_products_lng w ON z.productid = w.productid
AND w.code =  'US'
WHERE z.forsale =  'Y'
group by z.product_t

因此使用最左侧的索引字段(product_t),执行时间仍然很长:

+-----------+--------------------+
| product_t | COUNT(z.productid) |
+-----------+--------------------+
| B         |                  4 |
| C         |              10521 |
| D         |                  1 |
| F         |                 16 |
| G         |                363 |
| J         |                 16 |
| L         |                749 |
| M         |                 22 |
| O         |                279 |
| P         |               5304 |
| S         |                 22 |
| W         |                662 |
+-----------+--------------------+
12 rows in set (0.81 sec)

当我使用整个索引(product_t,productid,forsale)时,执行时间非常快(0.005秒)。我应该如何更改它以使查询更快?

enter image description here

我认为通过使用半连接可以改善查询......但是我不确定如何......

3 个答案:

答案 0 :(得分:2)

减速可能与GROUP BY子句无关。尝试单独为w.code和z.forsale添加索引。

MySQL Profiling也可能对您的努力有所帮助

答案 1 :(得分:0)

最明显的答案是仅为product_t创建新索引。您创建新索引吗?

答案 2 :(得分:0)

谢天谢地,我找到了一种如何提高速度的方法。我确实有另一个表,其中定义了所有product_t。每个product_t还使用'code'字段(指定每个product_t的翻译)。在这个表中,我有一个在product_t和代码上定义的索引。通过将查询更改为:

SELECT z.product_t, COUNT(z.productid)
FROM xcart_products z
JOIN xcart_products_lng w ON z.productid = w.productid
JOIN xcart_products_product_t_lng p ON z.product_t = p.product_t
AND p.code =  'US'
WHERE z.forsale =  'Y'
group by p.product_t,p.code

我设法将速度提高到0.10秒。之所以更快是因为分组现在是在整个索引上完成的。其次,code ='US'从大的products_lng表替换到小的product_t_lng表。我认为这是查询最有效的...

mysql> SELECT z.product_t, COUNT( z.productid )
        -> FROM xcart_products z
        -> JOIN xcart_products_lng w ON z.productid = w.productid
        -> JOIN xcart_products_product_t_lng p ON z.product_t = p.product_t
        -> AND p.code =  'US'
        -> WHERE z.forsale =  'Y'
        -> GROUP BY p.product_t, p.code
        -> ;
    +-----------+----------------------+
    | product_t | COUNT( z.productid ) |
    +-----------+----------------------+
    | B         |                    4 |
    | C         |                10521 |
    | F         |                   16 |
    | G         |                  363 |
    | L         |                  749 |
    | M         |                   22 |
    | O         |                  279 |
    | P         |                 5304 |
    | S         |                   22 |
    | W         |                  662 |
    +-----------+----------------------+
    10 rows in set (0.14 sec)