PostgreSQL 9.3-元素包含在vs之间

los*_*rse 3 sql postgresql postgresql-9.3

我有一张大的(3000万行)简单的桌子...

CREATE TABLE "Foo"."Bar" (
    "BarID" BIGSERIAL PRIMARY KEY,
    "DateTime" TIMESTAMP NOT NULL,
    "Bar" TEXT NOT NULL
);
Run Code Online (Sandbox Code Playgroud)

...一个简单的索引:

CREATE INDEX ON "Foo"."Bar"("DateTime");
Run Code Online (Sandbox Code Playgroud)

...和一个简单的问题:

在2015年的第一个小时,哪些"BarID"值具有"DateTime"价值?


因此,我进行了以下查询#1:

SELECT
    "Bar"."BarID"
FROM
    "Foo"."Bar"
WHERE
    "Bar"."DateTime" <@ TSRANGE('2015-01-01 00:00:00', '2015-01-01 01:00:00');
Run Code Online (Sandbox Code Playgroud)

...以及此查询#2:

SELECT
    "Bar"."BarID"
FROM
    "Foo"."Bar"
WHERE
    "Bar"."DateTime" BETWEEN '2015-01-01 00:00:00' AND '2015-01-01 01:00:00';
Run Code Online (Sandbox Code Playgroud)

结果

查询#1在60秒内通过序列扫描运行。

使用索引扫描,查询2在0.02秒内运行。

我尝试制作另一个USING GiST没有改善的索引。

是什么赋予了?

Mik*_*ll' 5

范围表达式是可修饰的。您只需要一个范围表达式可以使用的索引。在“时间戳”类型的列上有一个B树索引和一个GiST索引。时间戳范围表达式不能利用这些索引中的任何一个。

在时间戳范围表达式上创建GiST索引,并更新统计信息。

create index on "Foo"."Bar" 
using gist(tsrange("DateTime"::timestamp, "DateTime"::timestamp, '[]'));

analyze "Foo"."Bar";
Run Code Online (Sandbox Code Playgroud)

你的“日期时间”列表示在时间点,所以时间戳范围表达应具有包容性降低上限('[]')。

重写WHERE子句以使用相同的表达式。

explain analyze
select "BarID"
from "Foo"."Bar"
where tsrange("DateTime"::timestamp, "DateTime"::timestamp, '[]') <@ tsrange('2015-01-01 00:00:00', '2015-01-01 01:00:00');
Run Code Online (Sandbox Code Playgroud)

该查询可以使用索引,它在大约一百万行的表上大约半毫秒内在此处运行。

“在“条形图”上进行位图堆扫描(成本= 10.19..859.53行= 246宽度= 8)(实际时间= 0.195..0.551行= 219循环= 1)”
“重新检查条件:(tsrange(“ DateTime”,“ DateTime”,'[]':: text)<@'[“ 2015-01-01 00:00:00”,“ 2015-01-01 01:00: 00“)':: tsrange)”
“->在“ Bar_tsrange_idx”上进行位图索引扫描(成本= 0.00..10.13行= 246宽度= 0)(实际时间= 0.160..0.160行= 219循环= 1)”
“索引条件:(tsrange(“ DateTime”,“ DateTime”,'[]':: text)<@'[“ 2015-01-01 00:00:00”,“ 2015-01-01 01:00: 00“)':: tsrange)”
“总运行时间:0.589毫秒”