获取最新值-sql执行时间太长

获取最新值-sql执行时间太长,sql,firebird,Sql,Firebird,我有一个Firebird数据库,它的表有两列:Date和value 我想得到最近的值。问题是,这个表很容易有超过200k行。我的select查询耗时超过400ms,这对于我的应用程序来说太长了。有没有办法,我可以加快速度 我无法以任何方式更改数据库。我不能使用Firebird 3.0中引入的任何窗口函数 我的问题是: SELECT REG_DATE_TIME,REG_VAL FROM TAB_REG_VAL WHERE REG_DATE_TIME = (SELECT MAX(REG_DAT

我有一个Firebird数据库,它的表有两列:Date和value

我想得到最近的值。问题是,这个表很容易有超过200k行。我的select查询耗时超过400ms,这对于我的应用程序来说太长了。有没有办法,我可以加快速度

我无法以任何方式更改数据库。我不能使用Firebird 3.0中引入的任何窗口函数

我的问题是:

SELECT  REG_DATE_TIME,REG_VAL FROM TAB_REG_VAL  
WHERE REG_DATE_TIME = (SELECT MAX(REG_DATE_TIME)  FROM TAB_REG_VAL);
我还尝试了
select first。。order by
,但执行时间相似。 我正在使用C#ado.net连接层,如果这很重要的话。

我会尝试:

SELECT FIRST (1) REG_DATE_TIME, REG_VAL
FROM TAB_REG_VAL  
ORDER BY REG_DATE_TIME DESC;
选项卡上有一个索引\u REG\u VAL(REG\u DATE\u TIME,REG\u VAL)

我会尝试:

SELECT FIRST (1) REG_DATE_TIME, REG_VAL
FROM TAB_REG_VAL  
ORDER BY REG_DATE_TIME DESC;

使用
选项卡上的索引\u REG\u VAL(REG\u DATE\u TIME,REG\u VAL)
您需要为列
REG\u DATE\u TIME
创建降序:

create descending index idx_tab_reg_val_reg_date_time on TAB_REG_VAL(REG_DATE_TIME);
然后您可以使用

SELECT FIRST 1 REG_DATE_TIME,REG_VAL 
FROM TAB_REG_VAL
ORDER BY REG_DATE_TIME DESC
如果没有索引,Firebird将需要对整个结果集进行具体化和排序,然后才能返回第一行。这是低效的(如果结果集大于排序内存,情况会更糟,在这种情况下Firebird将在磁盘上的临时文件中排序)

使用索引,Firebird只需要访问索引中的几页和表中的一条或多条记录,就可以找到事务可见的第一条记录


注意:Firebird索引目前只能用于按单个方向排序,这意味着根据您的访问需要,您可能还需要按升序方向创建索引。

您需要为列
REG\u DATE\u TIME
创建降序索引:

create descending index idx_tab_reg_val_reg_date_time on TAB_REG_VAL(REG_DATE_TIME);
然后您可以使用

SELECT FIRST 1 REG_DATE_TIME,REG_VAL 
FROM TAB_REG_VAL
ORDER BY REG_DATE_TIME DESC
如果没有索引,Firebird将需要对整个结果集进行具体化和排序,然后才能返回第一行。这是低效的(如果结果集大于排序内存,情况会更糟,在这种情况下Firebird将在磁盘上的临时文件中排序)

使用索引,Firebird只需要访问索引中的几页和表中的一条或多条记录,就可以找到事务可见的第一条记录



注意:Firebird索引目前只能用于单向排序,这意味着根据您的访问需要,您可能还需要创建一个升序索引。

此表的索引定义是什么?涉及的数据类型是什么?对于
reg\u val
:列的宽度是多少(即:平均实际长度是多少)?您多久写入一次该表,多久读取一次?另一个解决方案可能是创建一个特殊的缓存表,您的数据库触发器将在其中复制最新的行。@markrotVeel还没有索引。Reg val是float,实际长度实际上取决于表(用户指定)@KarolŻurowski的频率在这里并不重要,比率是重要的。2:1的r:w缓存当然没有什么意义。但是它会像10:1一样,或者可能是WWW 100:1或更多的典型情况-那么缓存可能比索引更好这个表的索引定义是什么?还涉及哪些数据类型,对于
reg\val
:它的宽度是多少e列(即:实际平均长度是多少)?您多久写入一次该表,多久读取一次?另一个解决方案可能是创建一个特殊的缓存表,您的数据库触发器将在其中复制最近的行。@MarkRotVeel还没有索引。Reg val是float,实际长度实际上取决于表(用户指定)@KarolŻurowski的频率在这里并不重要,比率是重要的。2:1的r:w缓存当然没有什么意义。但是它会像10:1或者可能是WWW 100:1或更多的典型情况吗?那么缓存可能比indexIn Firebird更好。你不能在索引中对单个列进行排序,只能对整个索引进行排序,包括
reg\val
co用于此目的的列不会有额外的好处,因为Firebird无论如何都需要读取实际行以检查事务可见性。在Firebird中,您不能对索引中的单个列进行排序,只有作为一个整体的索引(包括用于此目的的
reg\u val
列)不会有额外的好处,因为Firebird需要读取实际的行仍然可以检查事务可见性。谢谢。我的查询时间从400ms减少到20ms左右!!!我必须运行一些测试,但一切看起来都很好。另外,添加此索引会改变什么吗?因为我的其他程序依赖于此数据库。@KarolŻurowski功能上不会改变,但会有一个(非常小的)insert/update/delete的性能会受到影响,因为索引也会被更新(这通常只有在表上有很多索引时才明显)。如果其他应用程序执行类似的选择,它们也可能从该索引中获得更高的性能。“FIRST 1”如果实际上可能有多行具有相同的时间戳,则会产生不同的结果(读取多个传感器或多通道传感器时正常)@Arioch'如果记录有重复的时间戳,即使没有索引,结果也不稳定,并且有了索引,除非记录得到更新,否则顺序或多或少会得到保证。@MarkrotVeel我的意思是与他的初始查询比较
select…,其中timestamp=(选择max)
这将发出所有这些行,而不仅仅是其中一行。谢谢。我的查询时间从400毫秒减少到20毫秒左右!!!我必须运行一些测试,但一切看起来都很好。此外,添加此索引会改变什么吗?因为我的其他程序依赖于此数据库。@KarolŻurowski功能上不会改变,但会有一个错误(非常小)insert/update/delete对性能的影响,因为索引也将被更新(这通常只有在表上有很多索引时才明显)。如果其他应用程序执行类似的选择,它们也可能从该索引中获得更高的性能。如果