MySQL+Laravel下1500万+记录高效查询近7天数据方案咨询
高效查询近7天实时数据的解决方案
基于你已有的created_at索引、每秒新增数据且需实时查询的场景,以下是几个实用的高效方案:
严格使用范围查询(避免索引失效)
绝对不要对created_at字段使用函数包装(比如DATE(created_at) >= CURDATE() - INTERVAL 7 DAY),这种写法会导致索引失效,触发全表扫描。正确的写法是直接用字段本身做范围比较:SELECT * FROM your_table WHERE created_at >= NOW() - INTERVAL 7 DAY;这条语句会直接走
created_at的B+树索引,快速定位到近7天的数据范围,扫描行数极小。时间分区表优化
针对这种持续写入的时间序列数据,按时间维度做分区(比如按天或按周)是很有效的优化手段。以MySQL为例,创建RANGE分区的示例:CREATE TABLE your_table ( id INT AUTO_INCREMENT PRIMARY KEY, created_at DATETIME NOT NULL, -- 其他字段 ) PARTITION BY RANGE (TO_DAYS(created_at)) ( PARTITION p20240501 VALUES LESS THAN (TO_DAYS('2024-05-02')), PARTITION p20240502 VALUES LESS THAN (TO_DAYS('2024-05-03')), -- 后续可以通过脚本自动新增分区 );查询近7天数据时,数据库只会扫描对应的7个分区,而不是全表,大幅减少IO开销。同时分区表的清理(比如删除超过30天的旧数据)也会更高效。
覆盖索引减少回表
如果你的查询只需要特定字段(不是SELECT *),可以创建包含这些字段的联合覆盖索引,避免查询时的回表操作。比如你需要查询id、content和created_at,可以创建:CREATE INDEX idx_created_at_include ON your_table (created_at) INCLUDE (id, content); -- 或者在不支持INCLUDE的数据库中,直接创建联合索引: CREATE INDEX idx_created_at_id_content ON your_table (created_at, id, content);这样查询时直接从索引中获取所有需要的数据,不需要再去访问主表,性能会提升很多。
读写分离分摊压力
如果查询频率很高,主库同时承担写入和查询可能会有压力,可以搭建读写分离架构:主库负责每秒的写入操作,从库负责近7天数据的查询。注意要选择延迟低的同步方案(比如半同步复制),确保从库的数据和主库几乎实时一致,满足你获取最新信息的需求。
内容的提问来源于stack exchange,提问作者Derek Hale
相关产品推荐
相关产品推荐

