HSQLDB 2.7.4 带OFFSET的索引查询性能低下问题求助
各位好,我在使用HSQLDB 2.7.4时遇到了一个困惑的性能问题,想请教下大家的思路。
按照我对官方文档的理解,当在带索引的查询中使用OFFSET时,应该会利用索引来计算偏移量,从而避免全表扫描的性能损耗,但实际测试下来大偏移量场景下性能暴跌,完全没达到预期。
先给大家看我的测试细节:
- 小偏移量查询(耗时仅17ms):
SELECT id FROM news ORDER BY id DESC LIMIT 25 offset 25;
- 大偏移量查询(耗时飙升至1.31秒):
SELECT id FROM news ORDER BY id DESC LIMIT 25 offset 80000;
我的表结构很简单,ID是自增主键:
CREATE TABLE NEWS ( ID INTEGER GENERATED BY DEFAULT AS IDENTITY, -- 其他字段省略 ); ALTER TABLE NEWS ADD PRIMARY KEY (ID);
我查看了大偏移量查询的执行计划,发现它居然做了全表扫描:
isDistinctSelect=[false] isGrouped=[false] isAggregated=[false] columns=[ COLUMN: PUBLIC.NEWS.ID not nullable ] [range variable 1 join type=INNER table=NEWS cardinality=81400 access=FULL SCAN join condition = [index=SYS_IDX_SYS_PK_10815_10822 ] ]] order by=[ COLUMN: PUBLIC.NEWS.ID DESC uses index] offset=[ VALUE = 80000, TYPE = INTEGER] limit=[ VALUE = 25, TYPE = INTEGER] PARAMETERS=[] SUBQUERIES[]
而官方文档里明确写了:
Indexes and ORDER BY, OFFSET and LIMIT
HyperSQL can use an index on an ORDER BY clause if all the columns in ORDER BY are in a single-column or multi-column index (in the exact order). This is important if there is a LIMIT n (or FETCH n ROWS ONLY) clause. In this situation, the use of an index allows the query processor to access only the number of rows specified in the LIMIT clause, instead of building the whole result set, which can be huge.
我本来以为我的场景完全符合文档描述——ORDER BY的ID是单列主键索引,但执行计划却显示走了全表扫描,大偏移量时要先扫描8万多行再取后面25条,性能自然差。
更奇怪的是,我尝试不用OFFSET,改用WHERE条件过滤ID,结果也有反直觉的表现:
SELECT id FROM news where id>80000 ORDER BY id DESC limit 25耗时12ms(符合预期)SELECT id FROM news where id>80 ORDER BY id DESC limit 25反而耗时1.5秒(小范围过滤反而更慢)
有没有大佬能帮忙分析下这背后的原因?或者有没有什么优化的办法能让大偏移量的查询用上索引?
谢谢大家的帮助!
内容来源于stack exchange

