PostgreSQL 中的快速查询

Fast query in PostgreSQL

我有一个非常大的数据库 (~1TB),所以 运行 即使是一个非常简单的查询也可能需要很长时间。例如。对于:

EXPLAIN select count(*) from users; 

成本为 44661683.87 磁盘页面获取。因此执行起来非常昂贵。 当我尝试对查询进行限制时:

EXPLAIN select count(*) from users limit 10;

执行查询的成本保持不变,即 44661683.87 次磁盘页面提取。

那么 (1) 是否可以对数据子集执行查询,然后推断到 table 的其余部分?可以使用类似以下内容快速找到行大小:

SELECT reltuples AS approximate_row_count FROM pg_class WHERE relname = 'users';

此外,(2) 是否可以 select 随机分布的行子集?

select count(*) . . .是没有group by的聚合查询。它 returns 1 行,所以限制没有影响。

您似乎想要:

select count(*)
from (select u.*
      from users u
      limit 10
     );

关于你的第二个问题,Postgres 在 9.5 版本中引入了 tablesampleYou can investigate that.

is it possible to execute a query on subset of data and then extrapolate to the rest of the table

您可以使用 tablesample 选项:

select count(*) * 10
from the_table tablesample system (10);

tablesample system (10) 只会扫描 table 的 10% 的块,这应该是相当快的。如果将结果行数乘以 10,您将得到总行数的近似值(!)。样本量越小速度越快,这将是 - 但也不太准确。

数字的准确性取决于 space 您的 table 有多少空闲,因为 10%(或您选择的任何样本大小)基于 table。如果有很多空闲(或半空闲)块,那么这个数字就不那么可靠了。

如果您在用户 table 上有一个主键索引(或另一列上的索引),您可以让它使用该索引进行 index-only 扫描,这应该会导致更好的执行计划。但是,奇怪的是,它不能与 COUNT 一起使用,因此您可以在子查询中执行 SELECT DISTINCT,然后在外部查询上执行 COUNT 以强制它使用索引:

EXPLAIN SELECT COUNT(*) FROM (SELECT DISTINCT id FROM users) u;