`

PostgreSQL表的行数统计

阅读更多
  原文地址:

  http://www.varlena.com/varlena/GeneralBits/120.php
引用
PostgreSQL表的行数统计

在很多情况下我们需要知道一个表的记录数有多少。如果你发现你有这样的需求,你还应该问问这样的统计的精确度到底又多高。如果你在做会计报表,你需要非常的精确。如果你做一个网页的记数器,可能有一些误差也是允许的。

  使用count(*)

  传统的计算一个表的行数的方法是使用count(*),但是count(*)非常的慢,尤其是对于一个大表而言。
webstat=# select count(*) from rawlog;
      count
    ---------
     2058704
    (1 row)

    Time: 7202.873 ms
  从上边的查询可以看出,count(*)的速度是非常的慢的,因此你应当尽可能的避免使用count(*),
但是它仍然是最精确的一种方法。

  使用系统表

  count(*)的一种替代方法是通过查找pg_class系统表获取大致的行数。这个数值每次vacuum之后
变化。你统计的行数的误差在vacuum之间删除或者插入的行数,如果你统计的行数允许这样的差值,
这种方法就是你最佳的选择。记住,别使用这种方法在会计统计上。当你发出的vacuum越频繁,则
你所得到的行数就越精确。

  这个数值存储在pg_class的reltuples字段里边,下边的查询语句列出了public模式下的所有表
的行数:
      
SELECT relname, reltuples
FROM pg_class r JOIN pg_namespace n
ON (relnamespace = n.oid)
WHERE relkind = 'r' AND n.nspname = 'public';

  对象的类型是表类型('r'),模式是public。相应的如果我们想看一个表的行记录数,我们可以
使用如下的语句:

SELECT reltuples
FROM pg_class r
WHERE relkind = 'r' AND relname = 'mytable';

  使用触发器

  如果你必须得到精确的记录数,而又不想使用count(*)的话,那么你可以考虑使用触发器来维护
表的记录数。这个办法需要创建一个INSERT TRIGGER来增加数量以及一个DELETE TRIGGER 来减少
数量。具体的数量可以存储在一个单独的表中。

  创建一个row_counts表,row_counts表包含一个表名称字段:relname,一个行记录数字段:
reltuples。首先你需要创建表,然后创建触发器,最后初试化表的记录数。

 
CREATE TABLE row_counts (
   relname  text PRIMARY KEY,
   reltuples   numeric);

  我写了一个触发器函数来处理表的Insert和Delete事件,我们可以很容易的通过TG_OP来判断操作
类型,TG_RELNAME来获取表的名称。这两个都是触发器的特殊变量。

CREATE OR REPLACE FUNCTION count_trig()
RETURNS TRIGGER AS
$$
    DECLARE
    BEGIN
      IF TG_OP = 'INSERT' THEN
          EXECUTE 'UPDATE row_counts set reltuples=reltuples +1 where relname = ''' || TG_RELNAME || '''';
          RETURN NEW;
       ELSIF TG_OP = 'DELETE' THEN
          EXECUTE 'UPDATE row_counts set reltuples=reltuples -1 where relname = ''' || TG_RELNAME || '''';
          RETURN OLD;
       END IF;
    END;
$$
LANGUAGE 'plpgsql';

  同样我也只写了一个函数来把所以的表上加上这个触发器。你可以不需要这样做。如果是这样的话,你可以
写一个相同的函数来删除触发器。

CREATE OR REPLACE FUNCTION add_count_trigs()
RETURNS void AS
$$
       DECLARE
          rec   RECORD;
          q     text;
       BEGIN
          FOR rec IN SELECT relname
                   FROM pg_class r JOIN pg_namespace n ON (relnamespace = n.oid)
                   WHERE relkind = 'r' AND n.nspname = 'public' LOOP
             q := 'CREATE TRIGGER ' || rec.relname || '_count BEFORE INSERT OR DELETE ON ' ;
             q := q || rec.relname || ' FOR EACH ROW EXECUTE PROCEDURE count_trig()';
             EXECUTE q;
          END LOOP;
       RETURN;
       END;
$$
LANGUAGE 'plpgsql';

  发出vacuum语句之后使用如下语句初试化表的记录数:

insert into row_counts select relname, reltuples from pg_class;

  可能还会存在一些错误,如任何在vacuum和创建触发器之间完成的事物都将忽略掉,为了精确的统计,你需要
停止服务器上的所有活动。

  即便你可以在每个表上运行vacuum,但是有的时候如果你不确定vacuum是否运行,你可以写个函数来完成相似
的功能。这个函数要比vacuum慢,而且如果你的数据库活动比较频繁的话也会有一些误差。

 
CREATE OR REPLACE FUNCTION init_row_counts()
RETURNS void AS
$$
       DECLARE
          rec   RECORD;
          crec  RECORD;
       BEGIN
          FOR rec IN SELECT relname
                   FROM pg_class r JOIN pg_namespace n ON (relnamespace = n.oid)
                   WHERE relkind = 'r' AND n.nspname = 'public' LOOP
             FOR crec IN EXECUTE 'SELECT count(*) as rows from '|| rec.relname LOOP
                -- nothing here, move along
             END LOOP;
             INSERT INTO row_counts values (rec.relname, crec.rows) ;
          END LOOP;
   
       RETURN;
       END;
$$
LANGUAGE 'plpgsql';

  这个函数从pg_class里边查找所有的表,对每个表使用count(*)获取记录数。把上边的放在一块,下边
列出来了操作顺序:

   创建记录行数的表。
   创建触发器函数。
   如果可能停止服务器的活动。
   Vacuum表。
   在一个事物里边,在表上添加触发器,初试化记录数。

  这样从次以后,你可以通过查询行记录数的表来或者相应表的记录数。


分享到:
评论

相关推荐

    Kettle手册

    - Kettle支持连接多种数据库,例如MySQL、Oracle、SQL Server、PostgreSQL等。 - 用户可以在设置窗口中配置数据库连接,并指定如何使用数据库。 7. SQL编辑器与数据库浏览器: - SQL编辑器允许用户直接编写并...

    PostgreSQL 9.0 High Performance

    - **问题描述**:有时 PostgreSQL 生成的查询计划可能不是最优方案,特别是当统计信息过时或不准确时。 - **解决方法**:定期更新统计信息,必要时手动干预查询计划选择。 #### 四、案例分析 假设有一个电商应用,...

    PostgreSQL从菜鸟到专家

    - **count函数**:统计行数。 - **Min函数**:获取最小值。 - **Max函数**:获取最大值。 - **Sum函数**:求和。 - **Avg函数**:计算平均值。 - **子查询**:嵌套查询的使用场景。 - **返回多行记录的子查询**:...

    JAVA编写SVN统计代码数量系统

    3. **数据库集成**:项目中包含了数据库文件,可能是MySQL或PostgreSQL等关系型数据库,用于存储项目成员和代码提交的数据。Spring Boot可以通过配置自动连接数据库,并提供JPA(Java Persistence API)或MyBatis等...

    Understanding PostgreSQL Explain

    ANALYZE命令就是用来做这个的,它收集表中数据的统计信息,这些信息对于数据库查询优化器制定高效的查询计划至关重要。 文档接着提到了几个关键指标,如“Width”(宽度)、“Rows”(行数)和“Total cost”(总...

    PostgreSQL 优化器入门简介

    1. **统计信息收集**:PostgreSQL通过ANALYZE命令收集表和索引的统计信息,如行数、平均值、标准差等,这些信息用于优化器的决策。 2. **查询解析**:SQL语句被解析成解析树,表示查询的逻辑结构。 3. **重写规则**...

    postgresql-9.4.26-1-windows-x64.exe

    2. **即时统计信息**:改进了统计信息收集机制,使得数据库能更快速地获取关于表的统计信息,从而优化查询计划,提高查询效率。 3. **JSONB支持**:9.4版增加了对JSONB数据类型的支持,这是一种二进制格式的JSON...

    PGSQL统计一个数据库所有数据库空字段的函数

    在PostgreSQL(简称PGSQL)中,有时我们需要统计数据库中所有表的空字段数量。这在数据分析、数据清洗等场景下非常有用。下面详细介绍如何创建并使用一个自定义函数来实现这一功能。 #### 函数概述 该函数名为`...

    PostgreSQL9.6并行查询(中文)

    那些访问大量数据,却返回给用户很少行数的查询是并行查询效果收益最明显的(译者注:例如统计型查询)。本章介绍了并行查询如何工作的细节,以及它适用于哪些场景,因此用户可以了解到如何使用它。

    sql数据所有表每个表的条数.txt

    此条件确保只统计表的数据行数而非索引。 5. **`and objectproperty(b.id, 'IsMSShipped') = 0`** - `objectproperty(b.id, 'IsMSShipped')`: 使用`objectproperty`函数判断对象是否为系统内部对象。 - `= 0`: ...

    aqo:PostgreSQL自适应查询优化

    5. **统计存储**:aqo需要一个存储结构来保存收集到的统计信息,这通常涉及到数据库的元数据或者专门的表。 6. **配置参数**:用户可以通过设置一系列的配置参数来控制aqo的行为,例如学习阶段的持续时间、何时进行...

    Postgresql查询效率计算初探

    `pg_class`中的`relpages`和`reltuples`分别表示表的页数和行数,`pg_stats`提供了关于列的统计信息,如平均值、标准差等,这些信息对优化器选择最佳执行路径至关重要。 总的来说,理解PostgreSQL的查询效率计算...

    PostgrSQL 实现原理,可以了解数据库内部是怎么实现的

    InPostgreSQL中,Statistics机制用于收集数据库的统计信息,例如表的行数、索引的选择性等。这些统计信息将被用于优化查询执行,提高数据库的性能。 《PostgreSQL 14 Internals》提供了PostgreSQL数据库内部实现...

    PostgreSQL教程(十):性能提升技巧

    在PostgreSQL中,最底层的节点通常是表扫描节点,包括顺序扫描、索引扫描和位图索引扫描等不同类型的扫描。顺序扫描涉及按顺序遍历整个表,而索引扫描则利用索引来快速定位数据。位图索引扫描适用于处理复杂的布尔...

    文件上传,能够实现自动统计功能

    此外,自动统计功能可能还需要数据库的支持,比如MySQL、PostgreSQL或MongoDB,以便存储和检索统计数据。数据统计结果通常会被存储在一个数据库表中,便于后续查询和展示。开发者可能还会创建一个用户友好的界面,让...

    yapgt:另一个PostgreSQL工具

    不要混淆太多不同的查询,不要混淆比较统计表的不同选择,您以前可能从未听说过。观看次数它提供什么?索引/顺序读取(seq_idx) 获取每个表启动的索引/顺序扫描的数量获取通过每个表的索引/顺序扫描( Hello缺少...

    ssd7 exercise10

    `pg_class`存储了PostgreSQL数据库中所有关系表的信息,包括表名(`relname`)、行数(`reltuples`)和页数(`relpages`)。这三张表的统计信息如下: - `lot`:行数249999,页数2865 - `customer`:行数249999,页数1908...

    pagila:PostgreSQL示例数据库

    - **分组和聚合**:计算总计、平均值等统计信息。 ```sql SELECT distributors.distributor_name, COUNT(*) FROM distributors JOIN films ON distributors.distributor_id = films.distributor_id GROUP BY ...

    pg12.2+pgpool4.3.2 for Centos7安装包及依赖包

    4. **改进的统计信息收集**:提供更精确的查询优化,通过更智能地估计表中的行数和分布来改善查询计划。 5. **空间索引**:对GiST和SP-GiST索引的优化,使得地理空间数据的查询更快。 6. **内存管理**:对内存分配和...

Global site tag (gtag.js) - Google Analytics