我有一个使用postgres的Web应用程序(Rails),它有表openings
。
openings
表有一些属性,与此查询相关的属性是valid_till
- datetime和'is_downloaded' - 布尔值。
现在几乎每个页面请求我都要检查是否有任何 - 有效的未下载开口。
如果valid_till
小于或等于current_time
且is_downloaded
为假,则开放有效并且未下载。
SELECT "openings".*
FROM "openings"
WHERE (valid_till >= CURRENT_TIMESTAMP and is_downloaded IS false)
LIMIT 1
我构建了一个sql查询我只想尽可能地优化它,因为它几乎会在每个页面请求中使用。随着时间的推移,openings
表将获得大量记录。
答案 0 :(得分:3)
你想要一个索引。我建议:
create index idx_openings_isdownloaded_validtill on openings(is_downloaded, valid_till)
但是,我要提醒的是,在没有limit
的情况下使用order by
通常是一个坏主意。如果没有order by
,它将返回一个不确定的匹配行。
编辑:
Jmelesky建议,过滤/部分索引可能更适合此查询:
create index idx_openings_isdownloaded_validtill
on openings(valid_till)
where not is_downloaded;
答案 1 :(得分:1)
现在几乎每个页面请求我都要检查是否有任何 - 有效的未下载开口。
然后使用EXISTS
:
SELECT CASE WHEN EXISTS(SELECT NULL FROM "openings"
WHERE valid_till >= CURRENT_TIMESTAMP
and is_downloaded IS false)
THEN 1
ELSE 0 END
EXISTS
的好处是编译器可以优化掉与匹配记录是否存在无关的任何计算。您也没有通过选择*
返回任何不必要的数据 - 您只是通过线路传输一个标量值。
提高此特定查询性能的最佳方法是在(valid_till, is_downloaded)
上设置复合索引。