【发布时间】:2021-12-09 07:43:14
【问题描述】:
我在 CodeIgniter 模型中使用了一个查询来获取特定日期之间的产品列表计数。当我的表中的项目较少时,这可以正常工作,但我的表中有超过 100,000 个条目,并且仅获得 2 天的输出大约需要 3-4 分钟。 from 和 to 天分开的时间越长,花费的时间就越多。
这里是查询:(Dbfiddle:https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=e7a99f08ecd217cbeb09fe6676cfe645)
with Y as (
with recursive D (n, day) as (
select 1 as n, '2021-09-25' my_date
union
select n+1, day + interval 1 day from D
where day + interval 1 day < '2021-10-15'
) select * from D
), X as (
select Y.day,
l.*,
(select status_from from logs
where logs.refno = l.refno
and logs.logtime >= Y.day
order by logs.logtime
limit 1) logstat
from listings l, Y
where l.added_date <= Y.day
), Z as (
select X.day, ifnull(X.logstat,X.status) stat_day, count(*) cnt
from X
group by X.day, stat_day
)
select Z.day,
sum(case when Z.stat_day = 'D' then Z.cnt else 0 end ) Draft,
sum(case when Z.stat_day = 'A' then Z.cnt else 0 end ) Action,
sum(case when Z.stat_day = 'Y' then Z.cnt else 0 end ) Publish,
sum(case when Z.stat_day = 'S' then Z.cnt else 0 end ) Sold,
sum(case when Z.stat_day = 'L' then Z.cnt else 0 end ) Let
from Z
group by Z.day
order by Z.day;
基本上,此查询所做的是从日期在所选日期范围期间和之后的日志中获取 status_from,并从日期在用户选择的起始日期范围之前的列表中获取 added_date 并计算它。检索到这些记录后,它会检查表中状态所包含的变量并执行sum(case when else 0) 以获取总数。
我认为查询速度慢的一个原因是它必须计算查询本身的状态总和,所以在 php 端执行计数部分可能会更快?如果是这样,那么我如何为其创建一个语句来迭代我的视图类中的计数。
当前视图类:
<?php
foreach($data_total as $row ){
$draft = $row->draft ? $row->draft : 0;
$publish = $row->publish ? $row->publish : 0;
$action = $row->action ? $row->action : 0;
$sold = $row->sold ? $row->sold : 0;
$let = $row->let ? $row->let : 0;
?>
<tr>
<td><?= $row->day?></td>
<td><?= $draft ?></td>
<td><?= $publish ?></td>
<td><?= $action ?></td>
<td><?= $sold ?></td>
<td><?= $let ?></td>
</tr>
<?php } ?>
或者如果可能的话,是否有任何方法可以更快地获得此查询的相同输出。
【问题讨论】:
-
您需要包含查询的解释结果、查询中所有受影响表的表定义(包括索引)。没有这些,很难回答你的问题!
-
我的第一个猜测是在过滤和/或排序的两个 TIMESTAMP 列上抛出索引:dbfiddle.uk/…
-
您需要向我们展示表和索引定义,以及每个表的行数。也许您的表格定义不佳。也许索引没有正确创建。也许您认为您在该列上没有索引。没有看到表和索引定义,我们无法判断。我们需要行计数,因为这会影响查询计划。如果您知道如何执行
EXPLAIN或获取执行计划,请将结果也放入问题中。如果您没有索引,请访问use-the-index-luke.com。 -
以
ALTER TABLE listings ADD INDEX added_date (added_date)开头。然后用你的真实数据(而不是 dbfiddle 上的小子集)在你的系统上做 EXPLAIN 或 EXPLAIN ANALYZE 并向我们展示输出。 -
@PeterTrcka 是的,我试过了,但返回 2 个条目仍然需要 3-4 分钟
标签: mysql sql query-optimization groupwise-maximum