HSQLDB 中 WHERE 和 ORDER BY 的性能问题

Posted

技术标签:

【中文标题】HSQLDB 中 WHERE 和 ORDER BY 的性能问题【英文标题】:Performance issue with WHERE and ORDER BY in HSQLDB 【发布时间】:2012-03-31 23:11:57 【问题描述】:

我有一个名为history_point 的简单表,其中包含以下列:

id - 整数PK device_id - 整数 registered - 时间戳 double_value - 双人间 channel - 整数 type - VARCHAR(100) int_value - 整数

该表还为以下列组合定义了索引:

id device_id registered channel device_id, channel, registered

该表包含大约 200000 行。我使用下面的 Java 代码运行查询。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class JdbcMain 
    public static void main(String[] args) throws Exception 
        Class.forName("org.hsqldb.jdbcDriver");
        Connection con = DriverManager.getConnection("jdbc:hsqldb:file:db/homeki.db;ifexists=true");
        Statement stmt = con.createStatement();
        long start = System.currentTimeMillis();
        ResultSet rs = stmt.executeQuery("<SQL query goes here>");
        if (rs.next()) 
            System.out.println("Registered: " + rs.getDate("registered"));
        
        long dur = System.currentTimeMillis() - start;
        System.out.println("Took " + dur + " ms.");
        stmt.execute("SHUTDOWN");
        con.close();
    

当我运行查询 SELECT * FROM history_point WHERE device_id = 3 AND channel = 0 LIMIT 1 时,大约需要 5 毫秒。如果我运行查询SELECT * FROM history_point ORDER BY registered DESC LIMIT 1,也需要大约 5 毫秒。 但是,如果我运行查询SELECT * FROM history_point WHERE device_id = 3 AND channel = 0 ORDER BY registered DESC LIMIT 1,大约需要 1000 毫秒!

考虑到他们在http://www.hsqldb.org/doc/1.8/guide/ch02.html#N1033B 上所说的话,我想这可以理解,“HSQLDB 不使用索引来改进查询结果的排序”(顺便说一句,这对我来说听起来很奇怪)。

然而,如果我使用 Eclipse Data Tools Platform 的 SQL Scrapbook 在 Eclipse 中运行最后一个查询,它会在大约 5 毫秒内执行。我使用 SQL Scrapbook 向它提出的任何查询都会在大约 5 毫秒内执行。这是为什么?它们都使用相同的 JDBC 驱动程序和相同的数据库。

history_point 中有大约 25000 行,device_id = 3channel = 0,如果这很重要的话。

我使用的连接字符串是jdbc:hsqldb:file:db/mystorage.db。该表被创建为CACHED 表(所有数据都存储在磁盘上)。

谁能解释一下?

提前致谢!

【问题讨论】:

哪个版本的 HSQLDB?如果您使用的是最新版本,请参考在线版本 2.x 指南。 你是绝对正确的。我使用 HSQLDB 2.2.8,并且正在查看 1.8 的指南。这是 HSQLDB 2.X 的相同部分:hsqldb.org/doc/2.0/guide/sqlgeneral-chapt.html#sgc_index_speed。似乎没有相同的限制(对 ORDER BY 使用索引)。但问题仍然存在.. 【参考方案1】:

如果 ORDER BY 列都被索引覆盖,并且查询条件可以使用不同的索引,则使用查询条件的索引。目前,HSQLDB可以使用(device_id, channel, registered)上的索引作为查询条件,但不能同时对registered列进行排序。

在 2.2.8 版本中,当存在 LIMIT 子句时,您可以强制使用 ORDER BY 列上的索引。在这种情况下,使用已注册的索引:

SELECT * FROM history_point WHERE device_id = 3 AND channel = 0 
ORDER BY registered DESC LIMIT 1 USING INDEX

但也许这是在三列上使用索引的最佳方式:

SELECT * FROM history_point WHERE device_id = 3 AND channel = 0 
ORDER BY device_id DESC, channel DESC, registered DESC LIMIT 1 USING INDEX

【讨论】:

该查询也会在约 1000 毫秒内执行。所以你的意思是这样的查询需要大约 1 秒来执行是合理的吗?为什么 Eclipse SQL Scrapbook 仍然显示所有提到的查询约 5 毫秒? 为您的查询执行 EXPLAIN PLAN 以查看使用了哪个索引。我不知道 Eclipse 中的执行时间。

以上是关于HSQLDB 中 WHERE 和 ORDER BY 的性能问题的主要内容,如果未能解决你的问题,请参考以下文章

Junit 测试用例 - HSQLDB count(...) over (partition ... order by ...)

在连接中使用 Where 子句,以及 Group by 和 Order By

sql里 where和order by一起使用是怎样的顺序

SQL语句中,如果有group by 和order by两个语句,是先分组还是先排序?

使用 WHERE、GROUP BY 和 ORDER BY

SQL语句中,如果有group by 和order by两个语句,是先分组还是先排序?