orders
表有2m记录。有大约900K的独特ship-to-id
s。
ship_to_id
上有一个索引(字段为int(8)
)。
以下查询需要近1000万才能完成。我已经PROCESSLIST
运行了Command
= Query
和State
= Sending Data
。
当我运行explain
时,会使用现有索引,possible_keys
为NULL
。
我有什么办法可以加快查询速度吗?感谢。
SELECT
ship_to_id as customer_id
FROM orders
GROUP BY ship_to_id
HAVING SUM( price_after_discount ) > 0
答案 0 :(得分:4)
看起来你没有有用的索引。尝试在price_after_discount上添加索引,并添加如下所示的where条件:
WHERE price_after_discount > 0
最小化你需要求和的行数,因为你显然可以丢弃任何0。
同时尝试运行“top”命令,并在查询运行时查看io“wait”列。如果它很高,则意味着您的查询会导致大量磁盘I / O.如果你有RAM来加速它(如果你使用innodb)或myisam是通过文件系统缓存完成的,你可以增加各种内存缓冲区。重新启动服务器将刷新这些缓存。
如果你没有足够的RAM(对于2M记录你不需要太多),那么考虑一个分区方案,可能是对于post-to-id列(如果你的mysql版本支持它)。
答案 1 :(得分:2)
如果该表中的所有订单都不是最新的(即不会再次更改),那么您可以将它们存档到另一个表中以减少需要扫描的数据量。
另一种选择是使用索引在表上抛出last_modified
时间戳。然后,您可以跟踪查询的运行时间并将结果存储在另一个表(query_results
)中。当再次运行查询时,您只需要选择自上次运行查询以来修改过的订单,然后使用它来更新query_results
。逻辑稍微复杂一点,但假设在查询执行之间更新了低百分比的订单,它应该快得多。
答案 2 :(得分:2)
MySQL 将使用group by
的索引,至少根据文档,here解释。
最有用的是,查询中使用的所有列都应该在索引中。这可以防止引擎引用原始数据和索引。因此,请尝试orders(ship_to_id, price_after_discount)
上的索引。