简体   繁体   English

使用date()函数时Postgres不使用索引

[英]Postgres not using index when using date() function

My schema is 我的架构是

CREATE TABLE a (
  id     BIGINT PRIMARY KEY,
  dt     TIMESTAMP NOT NULL
);

and I have created an index on dt: 并且我在dt上创建了一个索引:

CREATE INDEX a_dt_index ON a (dt);

The index is working fine when I use a query like 当我使用类似的查询时,索引工作正常

SELECT *
FROM a
WHERE dt >= '2008-12-30' AND dt < '2008-12-31';

However when I use the date() function the index isn't used. 但是,当我使用date()函数时,没有使用索引。

SELECT *
FROM a
WHERE date(dt) = '2008-12-30'

In my opinion the two queries a semantically the same, so why is the index not used? 我认为这两个查询在语义上是相同的,那么为什么不使用索引呢? Why I have to create an explicit date() index? 为什么我必须创建一个显式的date()索引?

CREATE INDEX a_date_index ON a (date(dt));

You may read following link to learn more about indexes and date . 您可以阅读以下链接以了解有关索引和日期的更多信息。 But TL;DR 但是TL; DR

functions are black boxes to the database. 函数是数据库的黑匣子。

Therefore 因此

If you use any function in your where clauses, you need to create an explicit index with that function. 如果在where子句中使用任何函数,则需要使用该函数创建一个显式索引。 Database does not understand your semantic equivalency. 数据库不了解您的语义等效性。

It is similar to case that 与情况类似

 WHERE UPPER(NAME)

does not use index in NAME column. 不使用“ NAME”列中的索引。 According to database UPPER function is not different than BLACKBOX . 根据数据库,UPPER功能与BLACKBOX并无区别。 Replace it. 代替它。

 WHERE BLACKBOX(NAME)

Look at a sample output of using the date function 查看使用date函数的示例输出

postgres# select id, date(dt), dt from a;
 id |    date    |             dt             
----+------------+----------------------------
  1 | 2014-12-15 | 2014-12-15 16:32:13.942183
  2 | 2014-12-15 | 2014-12-15 16:34:05.480178
(2 rows)

Time: 2.190 ms

The type of data stored is different. 存储的数据类型不同。

Somebody else might use the function a different way: 其他人可能会以其他方式使用该函数:

postgres#  SELECT *
FROM a
WHERE dt >= '2014-12-15 16:33' AND dt < '2014-12-16 ';
 id |             dt             
----+----------------------------
  2 | 2014-12-15 16:34:05.480178
(1 row)

Time: 2.168 ms
postgres#  SELECT *
FROM a
WHERE date(dt) >= '2014-12-15 16:33' AND dt < '2014-12-16 ';
 id |             dt             
----+----------------------------
  1 | 2014-12-15 16:32:13.942183
  2 | 2014-12-15 16:34:05.480178
(2 rows)

I didn't find the function in docs!! 我在文档中找不到该功能! But here is the description: 但是这里是描述:

postgres# \df+ date()
                                                                                   List of functions
Schema   | Name | Result data type |     Argument data types     |  Type  | Security | Volatility |  Owner   | Language |   Source code    |               Description                
------------+------+------------------+-----------------------------+--------+----------+------------+----------+----------+------------------+------------------------------------------
 pg_catalog | date | date             | abstime                     | normal | invoker  | stable     | postgres | internal | abstime_date     | convert abstime to date
 pg_catalog | date | date             | timestamp without time zone | normal | invoker  | immutable  | postgres | internal | timestamp_date   | convert timestamp to date
 pg_catalog | date | date             | timestamp with time zone    | normal | invoker  | stable     | postgres | internal | timestamptz_date | convert timestamp with time zone to date
(3 rows)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM