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 版本中引入了 tablesample
。 You 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;
我有一个非常大的数据库 (~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 版本中引入了 tablesample
。 You 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;