使用变量过滤器更快地进行 PostgreSQL 查询
Posted
技术标签:
【中文标题】使用变量过滤器更快地进行 PostgreSQL 查询【英文标题】:Making a PostgreSQL query with variable filters faster 【发布时间】:2021-02-17 11:07:02 【问题描述】:所以我有以下查询:
WITH temp_table as (
SELECT *, ROW_NUMBER() OVER (ORDER BY id ASC) AS rownum
FROM table
WHERE name = ?
AND bool_value != True
ORDER BY ?
)
SELECT *
FROM temp_table
WHERE column1 = ?
and column2 = ?
and column3 = ?
此查询通常返回大约 100k+ 行,但完成大约需要 20 秒。我想尽量减少这个时间。根据执行查询的用户,名称会有所不同。 'WHERE column1 = ? and column2 = ? and column3 = ?'
部分将根据用户想要检查的内容而有所不同;使用甚至可能不需要任何过滤器:
SELECT *, ROW_NUMBER() OVER (ORDER BY id ASC) AS rownum
FROM table
WHERE name = ?
AND bool_value != True
ORDER BY ?
用户还可以按不同的值对数据进行排序。
我已经尝试过建立索引,但无法找到正确的索引来加快查询速度。还有一个查询非常慢:
SELECT *
FROM table
WHERE bool_value = True
WHERE column1 = ?
and column2 = ?
and column 3 = ?
ORDER BY ?
此查询最多可返回 60k 行,用户无需输入任何过滤器,但大约需要 10-20 秒才能完成。
【问题讨论】:
请edit您的问题并添加使用explain (analyze, buffers, format text) select ...
生成的execution plan(不只是“简单”解释)作为@ 987654323@ 并确保保留计划的缩进。粘贴文本,然后将```
放在计划前一行和计划后一行。理想情况下适用于所有三个变体,但至少适用于第一个查询。
查询的 WHERE 子句中提到的列将用于确定哪些列应该进入索引。但是您告诉我们,在您的用户告诉您之前,您不知道涉及哪些列。恕我直言,这很难为您提供帮助。
所以你肯定需要来自beforecolumn1
,column2
,@上可能的过滤器的行号987654332@?这会迫使 Postgres 遍历所有候选行并保证速度很慢(除非您可以为只读数据实现行号)。
另外,PostgreSQL 版本是相关的。
【参考方案1】:
首先,CTE 中的order by
没有帮助(Postgres 不保证会遵循它),我建议将 CTE 写为:
SELECT t.*, ROW_NUMBER() OVER (ORDER BY id ASC) AS rownum
FROM table t
WHERE t.name = ? AND bool_value = False ;
注意:这里假设 bool_value
从来都不是 NULL
。
然后,对于这个查询,您需要一个索引:(name, bool_value, id)
。
我认为您对外部查询无能为力。
【讨论】:
以上是关于使用变量过滤器更快地进行 PostgreSQL 查询的主要内容,如果未能解决你的问题,请参考以下文章