以下 SQL 在 MySQL 中运行非常缓慢。对于 250,000 行的表(跨越 3 年的时间线),这需要一个多小时。
select L.order_date,
L.segname,
sum(O.product_total) as c_product_total,
sum(O.num_orders) as c_num_orders
from report_PurchasesByOrderDate_Hour_bySegment as L
join report_PurchasesByOrderDate_Hour_bySegment as O
on L.order_date >= O.order_date
and L.segname = O.segname
group by L.order_date, L.segname
;
此查询为每个段名(段名)生成每个日期的累积总和。我已经用索引解释了它。
有人对如何重写它以在 MySQL 上正常工作有任何想法吗?(此查询在 DB2 中运行良好,但我必须为这个项目使用 MySQL。)
谢谢你的帮助!
Tadman 要求我添加包含索引的表定义。(诚然,我最初应该发布的,所以这里是:
create table report_PurchasesByOrderDate_Hour_bySegment
(
order_date date not null,
hour_of_day int not null,
hourly_datetime datetime not null,
segname varchar(10),
product_total decimal(15,4),
num_orders bigint,
PRIMARY KEY (hourly_datetime, segname),
UNIQUE INDEX (order_date, hour_of_day, segname),
UNIQUE INDEX (hour_of_day, order_date, segname)
);
注意:hourly_datetime 列实际上是多余的,我在测试另一个查询的左连接性能时将其放入。
感谢您的反馈。hour_of_day 确实在不同的查询中使用。出于测试目的,我添加了以下索引。(这两个中只需要一个,但我现在创建了两个,看看哪个 MySQL 会使用。)
create index test1 on report_PurchasesByOrderDate_Hour_bySegment (order_date, segname);
create index test2 on report_PurchasesByOrderDate_Hour_bySegment (segname, order_date);
这是 MySQL Workbench 中使用的解释的解释输出:
id,select_type,table,type,possible_keys,key,key_len,ref,rows,Extra
1,SIMPLE,O,ALL,"order_date,test1,test2",NULL,NULL,NULL,253519,"Using temporary; Using filesort"
1,SIMPLE,L,ref,"order_date,test1,test2",test2,12,wc_store.O.segname,1267,"Using where; Using index"
我已经在自己的笔记本电脑和 Amazon Managed MySQL 数据库实例上运行了它。两者的解释是相同的。
附带说明为什么 hour_of_day 子句也在预先存在的索引中。有另一个版本的 select 是按 hour_of_day 聚合的。它的性能也很差(更差),但我发布了两个中较简单的一个,因为上面第一个的解决方案(如果有的话)可以应用于更复杂的示例。另一个版本将“L.hour_of_day”添加到选择列表和 group by 子句中,并在连接中有以下 on 子句:
on L.order_date >= O.order_date
and L.hour_of_day = O.hour_of_day
and L.segname = O.segname
更新 cbranch:正确,目标是每个日期都有一个汇总所有先前日期的运行总计。我更改了查询以匹配您提供的查询,这对于区分 order_date 和 segname 是正确的。但是它并没有提高性能。鉴于 MySQL 有时在连接中使用的子查询存在性能问题,我继续为子查询的结果创建了一个临时表并在其上放置索引。所以这是新版本:
create temporary table tmp_order_segment as
select distinct order_date, segname from report_PurchasesByOrderDate_Hour_bySegment;
create unique index tmp_1 on tmp_order_segment (order_date, segname);
create unique index tmp_2 on tmp_order_segment (segname, order_date);
select L.order_date,
L.segname,
sum(O.product_total) as c_product_total,
sum(O.num_orders) as c_num_orders
from tmp_order_segment as L
join report_PurchasesByOrderDate_Hour_bySegment as O
on L.order_date >= O.order_date
and L.segname = O.segname
group by L.order_date, L.segname;
不幸的是,这也没有提高性能。查询仍然运行了一个多小时。解释输出是:
id,select_type,table,type,possible_keys,key,key_len,ref,rows,Extra
1,SIMPLE,O,ALL,order_date,NULL,NULL,NULL,252264,"Using temporary; Using filesort"
1,SIMPLE,L,ref,"tmp_1,tmp_2",tmp_2,12,bsupply.O.segname,1,"Using where; Using index"
我在这个问题上尝试过的 MySQL 版本是:5.5.24 和 5.5.27。感谢您的任何帮助。