You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

电力公司开票系统多时间序列表查询性能优化请求

嘿,兄弟!第一次建数据库就能搞出电力开票系统,这已经很厉害了👍 咱们一步步来解决查询慢的问题,让你的系统能轻松扛住后面更复杂的计算。

先搞懂当前慢的原因

从你给的EXPLAIN结果能看出来:apxprice和powerload这两张表都在全表扫描(key列是null),只有imbalanceprice用到了索引。全表扫描几十万条数据再关联,速度肯定快不起来,而且越复杂的查询会越卡。

第一步:给另外两张表补全「精准的联合索引」

索引不是随便建的,要贴合你的查询逻辑来:

  • 对apxprice:你的查询需要用DATE关联,还要用PERIOD_FROM、PERIOD_UNTIL做范围判断,最后还要取PRICE计算。所以建一个包含这些字段的联合索引:
    CREATE INDEX idx_apx_date_period ON apxprice (DATE, PERIOD_FROM, PERIOD_UNTIL, PRICE);
    
    ✅ 把PRICE加进索引是为了「覆盖查询」——数据库直接从索引里拿数据,不用再去查整张表,速度会快很多。
  • 对powerload:查询用DATE和PERIOD_FROM关联,还要取POWERLOAD,所以建:
    CREATE INDEX idx_powerload_date_period ON powerload (DATE, PERIOD_FROM, POWERLOAD);
    

第二步:优化查询语句的写法

你用的是老式的逗号连接表,换成显式JOIN语法不仅更清晰,还能让数据库优化器更好地干活。另外还有个隐藏坑:你之前只按i.DATE分组,但SELECT里有PERIOD_FROM等非聚合字段,这在严格SQL模式下会报错,结果也不准确,必须把所有非聚合字段都加到GROUP BY里:

SELECT 
    i.DATE, 
    i.PERIOD_FROM, 
    i.TAKE_FROM_SYSTEM, 
    i.FEED_INTO_SYSTEM, 
    a.PRICE, 
    p.POWERLOAD, 
    SUM(a.PRICE * p.POWERLOAD) AS total_amount
FROM imbalanceprice i
JOIN apxprice a 
    ON i.DATE = a.DATE 
    AND i.PERIOD_FROM >= a.PERIOD_FROM 
    AND i.PERIOD_FROM < a.PERIOD_UNTIL
JOIN powerload p 
    ON i.DATE = p.DATE 
    AND i.PERIOD_FROM = p.PERIOD_FROM
WHERE i.DATE BETWEEN '2018-01-01' AND '2018-01-31'
GROUP BY i.DATE, i.PERIOD_FROM, i.TAKE_FROM_SYSTEM, i.FEED_INTO_SYSTEM, a.PRICE, p.POWERLOAD;

第三步:把MyISAM换成InnoDB(可选但推荐)

MyISAM是老掉牙的引擎了,不支持事务,在关联查询多的场景下性能远不如InnoDB。InnoDB有聚簇索引、行级锁,缓存机制也更高效,迁移起来超简单:

ALTER TABLE apxprice ENGINE=InnoDB;
ALTER TABLE imbalanceprice ENGINE=InnoDB;
ALTER TABLE powerload ENGINE=InnoDB;

迁移后主键会自动变成聚簇索引,对查询速度又是一波提升。

第四步:应对更复杂的查询(比如按月份分组全年数据)

如果要查全年数据并按月份分组,用DATE_FORMAT就能轻松实现,而且之前建的索引依然能发挥作用:

SELECT 
    DATE_FORMAT(i.DATE, '%Y-%m') AS month,
    SUM(a.PRICE * p.POWERLOAD) AS monthly_total
FROM imbalanceprice i
JOIN apxprice a 
    ON i.DATE = a.DATE 
    AND i.PERIOD_FROM >= a.PERIOD_FROM 
    AND i.PERIOD_FROM < a.PERIOD_UNTIL
JOIN powerload p 
    ON i.DATE = p.DATE 
    AND i.PERIOD_FROM = p.PERIOD_FROM
WHERE i.DATE BETWEEN '2018-01-01' AND '2018-12-31'
GROUP BY month;

最后别忘了验证效果

每次改完索引或语句,都跑一遍EXPLAIN看看:

  • apxprice和powerload的key列是不是显示了你新建的索引
  • rows列的数字是不是变小了(扫描行数越少越快)
  • extra列里的using temporary、filesort有没有减少

这样折腾完,你的查询速度肯定会有质的飞跃,后续加第三张电价表也能轻松hold住!

内容的提问来源于stack exchange,提问作者Introduction to programming

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 07:24:52