使用变量过滤器更快地进行 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 查询的主要内容,如果未能解决你的问题,请参考以下文章

创建一个查询,使用过滤器更快地以 XML 格式获取数据

更快地查找受时间限制的重复项

系统如何设计才能更快地查询到数据?

在 R 中更快地获得 randomForest 回归

如何在 PostgreSQL 的 DROP/CREATE/INSERT 语句中简洁地使用 SET 变量?

如何使用带有 OAuth 令牌的 Asp.Net MVC 中的 gmail API 更快地获取日期明智的电子邮件