【问题标题】:How to use index on function overlaps of postgres如何在postgres的功能重叠上使用索引
【发布时间】:2021-09-12 05:08:27
【问题描述】:

我使用 postgresSql 并使用重叠函数在表上查找范围时间。我的桌子看起来像

id room_id start_date start_time end_date    end_time delete_at
1  123    2021-01-09 10:00:00  2021-01-10   10:30:00 null
2  456    2021-08-10 15:00:00  2021-01-10   15:30:00 null
///some record
3600 789 2021-09-10  00:00:00 2021-09-10   15:00:00 null 

我的表很大,有 38000 条记录。 我写sql查找逻辑重叠时间的样子:

    select
        *
from
        booking as b
where
        b.room_id in ('123', '456', '789')
        and b.delete_flag = 0
        and (cast('2021-01-09 11:30:00' as TIMESTAMP),
        cast('2021-09-10 11:30:00' as TIMESTAMP)) overlaps ((b.start_date + bk.start_time),
        (b.end_date + b.end_time));

我已创建索引 start_date、start_time、end_date、end_time。但是 postgres 不能使用我的 index 。它只扫描序列。我创建新的多索引看起来像:

CREATE INDEX start_date_time_idx ON booking ((start_date + start_time))  
   CREATE INDEX end_date_time_idx ON booking ((end_date + end_time))

但是 postgres 不能使用 start_date_time_idx 和 end_date_time_idx 索引。我不明白为什么 postgres 不能使用索引。我尝试更改我的代码删除重叠但没有改变

       select
        *
from
        booking as b
where
        b.room_id in ('123', '456', '789')
        and b.delete_flag = 0
        and (cast('2021-01-09 11:30:00' as TIMESTAMP) > (b.start_date + bk.start_time),
        cast('2021-09-10 11:30:00' as TIMESTAMP))<= (b.end_date + b.end_time));

如何为函数重叠创建索引或如何在 mycase 中使用多个索引。为什么 start_date、start_time、end_date、end_time、start_date_time_idx、end_date_time_idx 的索引不能使用 mycase。请帮忙。谢谢。

【问题讨论】:

  • 您的查询不会针对指定的表运行。请向我们展示一个 CREATE TABLE 语句,然后清理您的问题,以便您显示的命令针对该创建的表运行。
  • @jjanes 我只是清楚地编辑了问题。请帮我。我调查了一些逻辑和方法,但我不明白为什么不能使用索引
  • 您的查询引用了不存在的表bk,第二个也有多个其他错误。我可以尝试猜测您的意思,当我这样做时确实使用了索引(但效率不高)

标签: sql postgresql


【解决方案1】:

据我所知,OVERLAPS 之所以存在,是因为它在 SQL 标准中,并且不支持 任何 索引方法。 PostgreSQL 风格的方法是使用范围,特别是 tsrange 或 tstzrange。

如果您从头开始,tstzrange 是正确的选择,但鉴于您的起点在时区方面已经被打破,这可能难以适应。从您现有的起点,您可以:

create index on booking using gist (tsrange((start_date + start_time),(end_date + end_time)));

这将支持在此 WHERE 子句上建立索引:

tsrange('2021-01-09 11:30:00','2021-09-10 11:30:00') && tsrange((b.start_date + b.start_time),(b.end_date + b.end_time));

尽管重新处理数据会更好,因此它只在表中存储一个 tstzrange,而不是 4 个不同的列。或者至少存储两个 timestamptz 列,用于开始和结束,而不是将每个列分成单独的日期和时间。

【讨论】:

  • 非常感谢。当我现在使用索引创建索引时。但是mysql使用两次:'2021-01-09 11:30:00'和'2021-09-10 11:30:00'。根据您的回答,它只使用 time : '2021-01-09 11:30:00'::timestamp 。如何在 tsrange 上两次工作 2021-01-09 11:30:00 和 2021-09-10 11:30:00。因为我需要两个时间并与 start_date、start_time、end_date、end_time 进行比较。
  • 抱歉,我没有注意到这两个日期是不同的——它们看起来非常相似,我虽然只是一个时刻。查看更新。
猜你喜欢
  • 1970-01-01
  • 2011-03-16
  • 2012-09-08
  • 1970-01-01
  • 1970-01-01
  • 2017-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多