代码之家  ›  专栏  ›  技术社区  ›  KarateKid

PostgreSQL中的快速查询

  •  0
  • KarateKid  · 技术社区  · 6 年前

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

    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)是否可以选择随机分布的行子集?

    3 回复  |  直到 6 年前
        1
  •  1
  •   a_horse_with_no_name    6 年前

    是否可以对数据子集执行查询,然后外推到表的其余部分

    您可以使用 tablesample 选项:

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

    tablesample system (10) 将只扫描表中10%的块,这应该相当快。如果将结果行数乘以10,则得到近似值(!)总行数的。样本量越小,速度越快,但精确度也越低。

    I数字的准确性取决于您的表有多少可用空间,因为10%(或您选择的任何样本大小)基于表中的块总数。如果有许多空闲(或半空闲)块,那么这个数字就不太可靠。

        2
  •  1
  •   Gordon Linoff    6 年前

    select count(*) . . . 是一个聚合查询,没有 group by . 它返回1行,因此限制没有影响。

    您似乎想要:

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

    关于你的第二个问题,博士后介绍 tablesample 在版本9.5中。 You can investigate that.

        3
  •  1
  •   Brady Holt    6 年前

    如果用户表上有一个主键索引(或另一列上的索引),则可以将该索引用于仅索引扫描,这将产生更好的执行计划。但是,奇怪的是,它不适用于COUNT,因此您可以在子查询中执行SELECT DISTINCT,然后对外部查询进行计数,以强制其使用索引:

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