PostgreSQL中的快速查询
我有一个非常大的数据库(~1TB),所以运行一个非常简单的查询可能需要很长时间。例如:PostgreSQL中的快速查询,sql,postgresql,postgresql-9.6,Sql,Postgresql,Postgresql 9.6,我有一个非常大的数据库(~1TB),所以运行一个非常简单的查询可能需要很长时间。例如: EXPLAIN select count(*) from users; 获取磁盘页的成本为44661683.87。因此,执行成本非常高。 当我尝试对查询设置限制时,如: EXPLAIN select count(*) from users limit 10; 执行查询的成本保持不变,即44661683.87磁盘页获取 那么(1)是否可以对数据子集执行查询,然后外推到表的其余部分?可以使用以下方法快速找到
EXPLAIN select count(*) from users;
获取磁盘页的成本为44661683.87。因此,执行成本非常高。
当我尝试对查询设置限制时,如:
EXPLAIN select count(*) from users limit 10;
执行查询的成本保持不变,即44661683.87磁盘页获取
那么(1)是否可以对数据子集执行查询,然后外推到表的其余部分?可以使用以下方法快速找到行大小:
SELECT reltuples AS approximate_row_count FROM pg_class WHERE relname = 'users';
此外,(2)是否可以选择随机分布的行子集?选择计数(*)
是一个聚合查询,没有分组依据
。它返回1行,因此限制没有影响
你似乎想要:
select count(*)
from (select u.*
from users u
limit 10
);
至于你的第二个问题,Postgres在9.5版中引入了tablesample
选择计数(*)
是一个聚合查询,没有分组依据
。它返回1行,因此限制没有影响
你似乎想要:
select count(*)
from (select u.*
from users u
limit 10
);
至于你的第二个问题,Postgres在9.5版中引入了tablesample
是否可以对数据子集执行查询,然后推断到表的其余部分
您可以使用tablesample
选项:
select count(*) * 10
from the_table tablesample system (10);
tablesample系统(10)
只扫描表中10%的块,这应该相当快。如果将结果行数乘以10,则总行数的近似值为(!)。样本量越小,速度越快,这将是-但也不太准确
I数字的准确性取决于您的表有多少可用空间,因为10%(或您选择的任何样本大小)基于表中的块总数。如果有许多空闲(或半空闲)块,那么这个数字就不太可靠
是否可以对数据子集执行查询,然后推断到表的其余部分
您可以使用tablesample
选项:
select count(*) * 10
from the_table tablesample system (10);
tablesample系统(10)
只扫描表中10%的块,这应该相当快。如果将结果行数乘以10,则总行数的近似值为(!)。样本量越小,速度越快,这将是-但也不太准确
I数字的准确性取决于您的表有多少可用空间,因为10%(或您选择的任何样本大小)基于表中的块总数。如果有许多空闲(或半空闲)块,那么这个数字就不太可靠 如果用户表上有一个主键索引(或另一列上的索引),可以让它将该索引用于仅索引扫描,这将产生更好的执行计划。但是,奇怪的是,它不能与COUNT一起工作,因此您可以在子查询中执行SELECT DISTINCT,然后对外部查询进行计数,以强制它使用索引:
EXPLAIN SELECT COUNT(*) FROM (SELECT DISTINCT id FROM users) u;
如果用户表上有一个主键索引(或另一列上的索引),可以让它将该索引用于仅索引扫描,这将产生更好的执行计划。但是,奇怪的是,它不能与COUNT一起工作,因此您可以在子查询中执行SELECT DISTINCT,然后对外部查询进行计数,以强制它使用索引:
EXPLAIN SELECT COUNT(*) FROM (SELECT DISTINCT id FROM users) u;
这不会改变任何事情。Postgres将扫描PK索引以查找
计数(*)
您确定吗?我刚刚在第9.6页的一个非常大的表上运行了SELECT COUNT(*)的EXPLAIN,它在表上显示了Seq Scan,而不是索引。仅索引扫描受最新统计数据和正确清空的表的约束-但我确实看到了几乎所有表的这一点。类似这样的事情:这不会改变任何事情。Postgres将扫描PK索引以查找计数(*)
您确定吗?我刚刚在第9.6页的一个非常大的表上运行了SELECT COUNT(*)的EXPLAIN,它在表上显示了Seq Scan,而不是索引。仅索引扫描受最新统计数据和正确清空的表的约束-但我确实看到了几乎所有表的这一点。大概是这样的: