如何优化超过 200 万行的 SQL 查询
P粉127901279
P粉127901279 2023-09-01 18:09:31
[MySQL讨论组]
<p>我有一个包含超过 200 万行的 Sql 数据库,并且增长速度很快。列不多,只有<code>代码、价格、日期和stationID</code>。</p> <p>目的是通过代码和stationID获取最新价格。 查询效果很好,但需要 10 多秒。</p> <p>有没有办法优化查询?</p> <pre class="brush:php;toolbar:false;">$statement = $this-&gt;pdo-&gt;prepare( 'WITH cte AS ( SELECT stationID AS ind, code, CAST(price AS DOUBLE ) AS price, date ,ROW_NUMBER() OVER( PARTITION BY code, stationID ORDER BY date DESC ) AS latest FROM price ) SELECT * FROM cte WHERE latest = 1 ' ); $statement-&gt;execute(); $results = $statement-&gt;fetchAll(PDO::FETCH_GROUP | PDO::FETCH_ASSOC);</pre> <p>编辑: 第一列有一个名为“id”的索引。我不知道这是否有帮助。</p> <p>数据库(InnoDB)如下所示:</p> <pre class="brush:php;toolbar:false;">id primary - int stationID - int code - int price - decimal(10,5) date - datetime</pre> <p>编辑2:</p> <p>结果需要按stationID分组,每个stationID需要显示多行。每个带有最新日期的代码一行。 像这样:</p> <pre class="brush:php;toolbar:false;">22456: code: 1 price: 3 date: 2023-06-21 code: 2 price: 2 date: 2023-06-21 code: 3 price: 5 date: 2023-06-21 22457: code: 1 price: 10 date: 2023-06-21 code: 2 price: 1 date: 2023-06-21 code: 3 price: 33 date: 2023-06-21</pre> <p>The json output should be 像这样:</p> <pre class="brush:php;toolbar:false;">{&quot;1000001&quot;:[{&quot;code&quot;:1,&quot;price&quot;:1.661,&quot;date&quot;:&quot;2023-06-06 12:46:32&quot;,&quot;latest&quot;:1},{&quot;code&quot;:2,&quot;price&quot;:1.867,&quot;date&quot;:&quot;2023-06-06 12:46:32&quot;,&quot;latest&quot;:1},{&quot;code&quot;:3,&quot;price&quot;:1.05,&quot;date&quot;:&quot;2023-06-06 12:46:32&quot;,&quot;latest&quot;:1},{&quot;code&quot;:5,&quot;price&quot;:1.818,&quot;date&quot;:&quot;2023-06-06 12:46:32&quot;,&quot;latest&quot;:1},{&quot;code&quot;:6,&quot;price&quot;:1.879,&quot;date&quot;:&quot;2023-06-06 12:46:32&quot;,&quot;latest&quot;:1}],&quot;1000002&quot;:[{&quot;code&quot;:1,&quot;price&quot;:1.65,&quot;date&quot;:&quot;2023-06-03 08:53:26&quot;,&quot;latest&quot;:1},{&quot;code&quot;:2,&quot;price&quot;:1.868,&quot;date&quot;:&quot;2023-06-03 08:53:26&quot;,&quot;latest&quot;:1},{&quot;code&quot;:6,&quot;price&quot;:1.889,&quot;date&quot;:&quot;2023-06-03 08:53:27&quot;,&quot;latest&quot;:1}],…</pre></p>
P粉127901279
P粉127901279

全部回复(2)
P粉141455512

我想您需要以下索引才能使查询良好执行(作为数据库设计的一部分,您只需执行一次)。

CREATE INDEX IX ON price
  (code, stationID, date DESC, price)

前两列可以按任意顺序排列。

P粉297434909

只要同一 code, stationID 对不能有两行具有相同的日期时间,使用窗口函数就有点像使用大锤敲开坚果。

select p.stationID, p.code, p.price, p.date
from (
    select code, stationID, max(date) as max_date
    from price
    group by code, stationID
) max
join price p
    on max.code = p.code
   and max.stationID = p.stationID
   and max.max_date = p.date;

它需要以下索引:

alter table price add index (code, stationID, date desc);

此查询应该花费不到 1 毫秒的时间,因为可以从索引构建派生表,然后它只从表中读取所需的行。

或者,如果您知道每个 code, stationID 对都会在特定时间段(1 小时、1 天、1 周)内收到更新的价格,那么您可以显着减少工作量窗口函数需要添加一个 where 子句:

with cte as 
(
    select stationID as ind, code, price, date, row_number() over(partition by code, stationID order by date desc) as latest
    from price
    where date >= now() - interval 1 week
)
select * from cte where latest  = 1;
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号