我正在尝试根据购买的商品数量“装箱”所有客户,并显示每个垃圾箱的数量。我正在尝试查看有多少人(account_id)购买了一件商品,购买了多少件商品,一直购买了9件商品,然后购买了10件商品。
这是我正在使用的查询 - 为了它的价值,我希望查询对销售进行全表扫描以生成结果,但整个过程需要永远!
我来自Oracle背景,我像在Oracle中一样编写了查询。
select thecnt
, count(*)
from (select count(*)
, case when count(*) >= 10 then 'tenormore' else cast(count(*) as char) end thecnt
from sales
where created >= SUBDATE( CURRENT_DATE(), INTERVAL 60 DAY )
group by account_id) sub
group by thecnt
order by thecnt;
在处理子查询时,mysql中是否有任何问题?
解释计划
+----+-------------+-------------------+-------+---------------+---------+---------+------+---------+----------+-----------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------------------+-------+---------------+---------+---------+------+---------+----------+-----------------------------------------------------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 2143248 | 100.00 | Using temporary; Using filesort |
| 2 | DERIVED | sales | range | created | created | 8 | NULL | 2012492 | 100.00 | Using where; Using index; Using temporary; Using filesort |
+----+-------------+-------------------+-------+---------------+---------+---------+------+---------+----------+-----------------------------------------------------------+
2 rows in set, 1 warning (1 hour 4 min 6.14 sec)
mysql> describe sales;
+-----------------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+---------------------+------+-----+---------+-------+
| account_id | char(36) | NO | PRI | NULL | |
| created | datetime | NO | MUL | NULL | |
| histogram_value | bigint(20) unsigned | NO | PRI | NULL | |
+-----------------+---------------------+------+-----+---------+-------+
答案 0 :(得分:1)
您可能缺少正确的索引。
编辑:
您的查询速度很慢,因为subquerys resut不适合内存并且正在使用磁盘上的临时表。
因此,您将受益于(account_id,created)上的索引,这会阻止它使用磁盘上的tmp表作为子查询(如果使用的话)
ALTER TABLE sales ADD INDEX ix_acc_cre (account_id, created)
答案 1 :(得分:1)
我没有看到您的查询有任何特别的错误。查询速度慢的原因是因为它需要使用临时表和filesort。严重加速此查询的唯一方法是修改MySQL设置以分配更多内存,以避免将磁盘用于这些进程。 Here's a spot on article covering the pertinent settings.
编辑:执行此操作后,您还可以通过指定要计数的精确列而不是COUNT(*)
来节省内存,以及其他一些小调整,如其他一些人所提到的那样。您希望获得尽可能小的数据集以充分利用您的记忆。但我认为除非你分配更多内存,否则整个问题不会消失。
答案 2 :(得分:0)
如果MySQL可以从索引中提取数据而不是查看实际行,则索引在全表扫描中非常有用。你不应该在这里需要子查询:
SELECT COUNT(account_id) AS thecnt,
IF(COUNT(account_id) < 10, COUNT(account_id), 'tenormore')
FROM sales
WHERE created >= SUBDATE( CURRENT_DATE(), INTERVAL 60 DAY )
GROUP BY account_id
ORDER BY thecnt DESC
希望这有帮助。