Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/87.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 无索引仅扫描索引中的日期转换_Sql_Postgresql - Fatal编程技术网

Sql 无索引仅扫描索引中的日期转换

Sql 无索引仅扫描索引中的日期转换,sql,postgresql,Sql,Postgresql,我创建以下表和索引: CREATE TABLE test ( id bigint, d timestamp without time zone ); CREATE INDEX f_date4 ON public.test USING btree (date(d), id); CREATE INDEX f_date5 ON public.test USING btree (id, date(d)); 我用数据填充表格并使用以下查询: SELECT id, date

我创建以下表和索引:

CREATE TABLE test
(
 id bigint,
 d timestamp without time zone
);

CREATE INDEX f_date4
  ON public.test
  USING btree
  (date(d), id);

CREATE INDEX f_date5
  ON public.test
  USING btree
  (id, date(d));
我用数据填充表格并使用以下查询:

SELECT id, date(d)
FROM test
WHERE date(d) > '2019-09-20'::date;
EXPLAIN
显示f_date4索引是在条件
d>'2019-09-20':date
下使用的,但我无法仅扫描
索引。可能的原因是什么,为什么会发生这种情况,以及如何避免这种情况

执行计划:

Index Scan using f_date4 on test  (cost=0.06..0.07 rows=1 width=12) (actual time=0.005..0.005 rows=0 loops=1)
Index Cond: (date(d) > '2019-01-20'::date)
Buffers: shared hit=2
Planning time: 0.131 ms
Execution time: 0.025 ms
我使用postgresql 10.6

提前谢谢

正如人们所说:

然而,PostgreSQL的规划者目前对此类案例并不十分精明

总而言之,计划者的一部分认为它需要“d”来计算日期(d)
,即使另一部分意识到它已经有了日期(d)。让这两个部分进行沟通并不容易


您可以构建索引
(日期(d),id,d)
来解决这个问题。

完整时间戳上的索引与截断时间戳上的索引具有相同的用途



结果查询计划:



@一匹没有名字的马我已经编辑了我的问题并添加了一个计划。没有更多的索引。这是一个测试表,是为了提问而创建的。它有1000行。同样的情况也发生在大约1亿行的表上。不相关,但为什么不直接执行
其中的d>'2019-09-20'::TIMESTAMP
,那么就不必费心进行所有这些日期转换了。@404在被截断的时间戳上建立索引也没有多大意义。而
其中d>='2019-09-21'
就足够了,IMHO。
CREATE TABLE test
(
 id bigserial PRIMARY KEY,
 d timestamp without time zone NOT NULL
);

INSERT INTO test(d)
select gs FROM generate_series('2019-01-01'::timestamp,'2020-01-01'::timestamp,'4 hour':: interval) gs
        ;

CREATE INDEX f_date4
  ON test
  USING btree (d, id);

CREATE INDEX f_date5
  ON test
  USING btree (id, d);


VACUUM ANALYZE test;

EXPLAIN ANALYZE
SELECT id, d::date
FROM test
WHERE d >= '2019-09-21' -- NOTE: slightly changed condition
        ;

CREATE TABLE
INSERT 0 2191
CREATE INDEX
CREATE INDEX
VACUUM
                                                       QUERY PLAN                                                        
-------------------------------------------------------------------------------------------------------------------------
 Index Only Scan using f_date4 on test  (cost=0.28..17.32 rows=612 width=12) (actual time=0.025..0.160 rows=613 loops=1)
   Index Cond: (d >= '2019-09-21 00:00:00'::timestamp without time zone)
   Heap Fetches: 0
 Planning Time: 0.285 ms
 Execution Time: 0.218 ms
(5 rows)