zoukankan      html  css  js  c++  java
  • PostgreSQL数据库一些tricks

    PostgreSQL自带Pgadmin客户端,可用于访问本地和远程PG库,一些tricks如下:

    1、联合查询

    SELECT * FROM table1 INNER JOIN table2 ON table1.id=table2.id
    
    # 其中table1,table2还可以分别用SQL选择如
    
    SELECT * FROM (SELECT * FROM table1 where num1=2 limit 10 offset 0) a INNER JOIN (SELECT * FROM  table2 where num2=4) b ON a.id=b.id

    2、索引

    # 查看pg库某表table1是否使用索引
    
    SELECT * FROM pg_indexes WHERE tablename='table1'
    
    # 对table1的某一列或者几列创建索引
    
    CREATE INDEX table1_index ON table1(num1, num2)  # table_index为建立的索引名称
    
    # 删除索引
    
    DROP INDEX table1_index

     2.1 复合索引

    多列复合索引的创建建议:

      1、离散查询条件(例如 等值)的列放在最前面,如果一个复合查询中有多个等值查询的列,尽量将选择性好(count(distinct) 值多的)的放在前面。

      2、离散查询条件(例如 多值)的列放在后面,如果一个复合查询中有多个多值查询的列,尽量将选择性好(count(distinct) 值多的)的放在前面。

      3、连续查询条件(例如 范围查询)的列放在最后面,如果一个复合查询中有多个多值查询的列,尽量将输入范围条件返回结果集少的列放前面,提高筛选效率(同时也减少索引扫描的范围)。

      4、如果返回的结果集非常大(或者说条件命中率很高),并且属于流式返回(或需要高效率优先返回前面几条记录),同时有排序输出的需求。建议按排序键建立索引。

    3、try...except的使用

      Postgres数据库中,同一事务中如果某次数据库操作中出错的话,那这个事务以后的数据库都会出错。

      即

    连接OPEN。
    try {
    
                   try {
    
                        数据库操作A。
    
                    } catch (Exception e) {
    
                        log.error("do something");
    
                    }
    
     
    
                   数据库操作B。   //此次数据操作有可能出现上面的错误。
    
                   事务提交commit。
    
               } catch (Exception ex) {
    
                   事务回滚rollback。
    
               } finally {
    
                   关闭连接。
    
               }
    View Code

    连接OPEN。
    
              try {
    
                   数据库操作A。
    
                   数据库操作B。
    
                   事务提交commit。
    
               } catch (Exception ex) {
    
                   数据库操作C。   //此次数据操作有可能出现上面的错误。
    
                   事务提交commit。
    
               } finally {
    
                   关闭连接。
    
               }
    View Code

    以上两种方式都会有问题

    我们可以在某个操作出错后加入事务提交或者回滚

      try {
    
                    数据库操作A。
    
              } catch (Exception e) {
    
                   事务回滚或者提交;
    
                   log.error("do something");
    
              }
    
              数据库操作B。 
    
    -----------------------------------------------------
       } catch (Exception ex) {
    
                   事务回滚或者提交;
    
                   数据库操作C。  
    
                   事务提交commit。
    
               } finally {
    
                   关闭连接。
    
               }
    View Code

     4、数据库清理

    4.1 日常清理(VACUUM;)

    日常清理(VACUUM;),因为有大量的更新(update)"删除(delete)操作,会有大量的空间需要释放。
    每日执行一次VACUUM,每周访问量低的时候执行VACUUM FULL;

    语法结构;
    
    VACUUM [ FULL | FREEZE ] [ VERBOSE ] [ table ]
    VACUUM [ FULL | FREEZE ] [ VERBOSE ] ANALYZE [ table [ (column [, ...] ) ] ]
    
    FULL ------选择"完全"清理,这样可以恢复更多的空间, 但是花的时间更多并且在表上施加了排它锁。
    FREEZE ---------选择激进的元组"冻结"。
    VERBOSE --------- 为每个表打印一份详细的清理工作报告。
    ANALYZE --------- 更新用于优化器的统计信息,以决定执行查询的最有效方法。
    table ------- 要清理的表的名称(可以有模式修饰)。缺省时是当前数据库中的所有表。
    column ---------要分析的具体的列/字段名称。缺省是所有列/字段。

    4.2 重建索引(REINDEX)

      语法
      REINDEX { INDEX | TABLE | DATABASE | SYSTEM } name [ FORCE ]

    描述

        REINDEX命令用来重建索引。旧的索引将被删除,重新读取索引的父表中的数据来重建索引。REINDEX命令不支持并发创建索引的功能。在下面的情况下,应该重建索引:
      (1)一个索引中的数据已被破坏,包含非法的数据。软件错误和硬件问题都会导致索引被损坏。
      (2)索引中包含许多空的或者几乎是空的数据页。应该重建索引,回收物理存储空间。
      (3)该变了索引的存储参数fillfactor的值,只有重建索引,新的参数值才能完全生效。
      (4)使用CREATE INDEX CONCURRENTLY命令创建索引时遇到错误,留下一个非法的索引。

     例子
      (1)重建索引my_index:REINDEX INDEX my_index;
      (2)重建表my_table 上的所有索引:REINDEX TABLE my_table;
      (3)重建数据库中的所有索引:REINDEX DATABASE broken_db;

    5、数据库、表大小查找

    #  表空间查找
    select pg_table_size('tablename')
    #  以kb、M、G等单位显示
    select pg_size_pretty(pg_table_size('tablename'))
    #  数据库查找
    select pg_database_size('database_name')
    # 查找所有数据库大小
    select pg_database.datname, pg_database_size(pg_database.datname) as size from pg_database

    6、批量插入

    当数据量比较大时,比如过亿的数据量要插入到数据库中,有几个策略可以提升速度:

      (1)创建unlogged的表,相当于内存表。

    create unlogged table   

        unlogged table 的几个特点:

          1、unlogged table不记录wal日志,写入速度快,备库无数据,只有结构。

          2、当数据库crash后,数据库重启时自动清空unlogged table的数据。

          3、正常关闭数据库,再启动时,unlogged table有数据。

          4、unlogged table通常用于中间结果,频繁变更的会话数据

      (2)多次insert后)再commit

          比如设置500次insert后再进行一次commit

      (3)开启多线程或者多进程

     7、数据表字段改变数据类型

      最近公司存数据遇到一个问题,给id 设为serial自增,后来发现不够用了,达到了2147483647顶峰值。当初没有考虑到这个问题,应该最初建表的时候设为bigserial就足够了,看看官网给的数据类型:

      

    NameStorage SizeDescriptionRange
    smallint 2 bytes small-range integer -32768 to +32767
    integer 4 bytes typical choice for integer -2147483648 to +2147483647
    bigint 8 bytes large-range integer -9223372036854775808 to 9223372036854775807
    decimal variable user-specified precision, exact up to 131072 digits before the decimal point; up to 16383 digits after the decimal point
    numeric variable user-specified precision, exact up to 131072 digits before the decimal point; up to 16383 digits after the decimal point
    real 4 bytes variable-precision, inexact 6 decimal digits precision
    double precision 8 bytes variable-precision, inexact 15 decimal digits precision
    serial 4 bytes autoincrementing integer 1 to 2147483647
    bigserial 8 bytes large autoincrementing integer 1 to 9223372036854775807

      因为给id设为主键,让它自增,其实建表时serial相当于将id设为int类型,然后会新建一个sequence,对于postgresql9.6以及更早的版本,这个sequence会以bigint建表,10.0以后的版本,sequence也是int类型,即自增数据列表为1-2147483647. 不清楚可以查询一下。

    `  假设建表如下:

    create table student(
      id serial PRIMARY KEY NOT NULL,
      name varchar(50)    
    )

          则同时会给建一个名为student_id_seq的序列表,还可以查看数据类型

    select * from student_id_seq

    结果中会显示sequence的数据类型,确定是int还是bigint。

    如果版本在9.6以前,只需要更改id的数据类型为bigint即可

    alter table student alter id type bigint

    如果版本在10.0以后,sequence数据类型也需要更改

    alter sequence student_id_seq as bigint;
    alter table student alter id type bigint;

    这样在查看数据类型,id就变味bigserial了

    8、主键自增序列初始值设定

    pg数据库当设定主键自增时,不管是serial还是bigserial,默认都是从1开始计数的。可是如果要指定从某个数开始计数该怎么办呢。比如从10000开始

    实现起来也很简单,假设建好一张表tablename为student,主键为number_id, 要求默认从10000开始计数。则可以用以下命令实现

    # SQL命令为
    select setval('tablename_pkname_seq',10000,false);
    # 我们这里即为
    select setval('student_number_id_seq',10000,false);

    9、创建数据库表时给字段添加注释

      不像mysql可以直接在创建表定义字段时直接加注释,pg数据库则是在创建后用 comment on column 命令注释。

    create table example(
    date_id int not null,
    company_id bigint not null,
    staff_id bigint not null)
    
    comment on column example.date_id is '日期';
    comment on column example.company_id is '公司id';
    comment on column example.staff_id is '员工id';
  • 相关阅读:
    #负分小组WEEK1#本周工作小结+下周计划
    #负分小组WEEK1#软件开发之路——需求获取与相关建模
    #负分小组WEEK1#第一次会议纪要
    #负分小组WEEK1#软件开发之路——准备阶段
    #负分小组WEEK1#确定项目——“宝宝睡吧!”儿童睡前服务服务软件+计划分工
    p6spy sql 执行记录
    apache common-lang3 工具类
    根据 ip 定位
    springcloud 与 spring boot 版本对应关系
    PowerDesign 基于mysql 数据库建模
  • 原文地址:https://www.cnblogs.com/zongfa/p/11638263.html
Copyright © 2011-2022 走看看