Jul*_*F-C 6 sql postgresql indexing performance correlated-subquery
我的问题由以下查询表示:
SELECT
b.row_id, b.x, b.y, b.something,
(SELECT a.x FROM my_table a WHERE a.row_id = (b.row_id - 1), a.something != 42 ) AS source_x,
(SELECT a.y FROM my_table a WHERE a.row_id = (b.row_id - 1), a.something != 42 ) AS source_y
FROM
my_table b
Run Code Online (Sandbox Code Playgroud)
我使用相同的子查询语句两次,以获得两者source_x
和source_y
.这就是为什么我想知道是否可以只使用一个子查询来做到这一点?
因为一旦我对我的真实数据(数百万行)运行此查询,它似乎永远不会完成并花费数小时,如果不是几天(我的连接在结束前挂起).
我正在使用PostgreSQL 8.4
我想你可以使用这种方法:
SELECT b.row_id
, b.x
, b.y
, b.something
, a.x
, a.y
FROM my_table b
left join my_table a on a.row_id = (b.row_id - 1)
and a.something != 42
Run Code Online (Sandbox Code Playgroud)
@DavidEG 发布了查询的最佳语法。
然而,你的问题绝对不仅仅是查询技术。使用一个JOIN
子查询而不是两个子查询最多可以将速度加快两倍。很可能更少。这并不能解释“小时”。即使有数百万行,设置得当的 Postgres 也应该在几秒钟而不是几小时内完成简单的查询。
首先值得注意的是查询中的语法错误:
... WHERE a.row_id = (b.row_id - 1), a.something != 42
Run Code Online (Sandbox Code Playgroud)
AND
这里需要or OR
,而不是逗号。
接下来要检查的是索引。如果row_id
不是主键,则可能没有索引。为了获得此特定查询的最佳性能,请创建一个多列索引,如下(row_id, something)
所示:
CREATE INDEX my_table_row_id_something_idx ON my_table (row_id, something)
Run Code Online (Sandbox Code Playgroud)如果过滤器每次都排除相同的值something != 42
,您还可以使用部分索引来提高速度:
CREATE INDEX my_table_row_id_something_idx ON my_table (row_id)
WHERE something != 42
Run Code Online (Sandbox Code Playgroud)
42
只有当它是一个公共值或者 something
是一个比整数更大的列时,这才会产生实质性的差异。integer
(由于数据对齐,具有两列的索引通常在磁盘上占用与仅具有一列的索引相同的大小。请参阅:
当性能成为问题时,检查您的设置总是一个好主意。Postgres 中的标准设置在许多发行版中使用最少的资源,并且无法处理“数百万行”。
根据您的 Postgres 实际版本,升级到当前版本(撰写本文时为 9.1)可能会有很大帮助。
最终,硬件也是一个因素。调整和优化只能让您到目前为止。
归档时间: |
|
查看次数: |
5960 次 |
最近记录: |