批量操作可以减少数据库与应用程序的交互次数,提高数据处理的吞吐量。本文将通过示例介绍如何批量插入、更新和删除数据。

您可以通过如下四种方法进行批量插入数据:

  • 使用 INSERT INTO ... SELECT 的方法。

    postgres=# INSERT INTO tbl1 (id, info ,crt_time) SELECT GENERATE_SERIES(1,10000),'test',NOW();    
      INSERT 0 10000    
      postgres=# SELECT COUNT(*) FROM tbl1;    
       count     
      -------    
       10001    
      (1 row)
  • 使用 VALUES(),(),...(); 的方法。

    postgres=# INSERT INTO tbl1 (id,info,crt_time) VALUES (1,'test',NOW()), (2,'test2',NOW()), (3,'test3',NOW());    
    INSERT 0 3
  • 使用 BEGIN; ...多条INSERT...; END; 的方法。严格来说,这不属于批量,但可以减少事务提交时的同步等待,同样可以提升性能。

    postgres=# BEGIN;    
    BEGIN    
    postgres=# INSERT INTO tbl1 (id,info,crt_time) VALUES (1,'test',NOW());    
    INSERT 0 1    
    postgres=# INSERT INTO tbl1 (id,info,crt_time) VALUES (2,'test2',NOW());    
    INSERT 0 1    
    postgres=# INSERT INTO tbl1 (id,info,crt_time) VALUES (3,'test3',NOW());    
    INSERT 0 1    
    postgres=# END;    
    COMMIT
  • 使用COPY协议。COPY协议与INSERT协议不一样,更加精简,插入效率高。

    test03=# \d test  
                      Table "public.test"  
        Column  |            Type             | Modifiers   
      ----------+-----------------------------+-----------  
       id       | integer                     | not null  
       info     | text                        |   
       crt_time | timestamp without time zone |   
      Indexes:  
          "test_pkey" PRIMARY KEY, btree (id)  
    
      test03=# COPY test FROM stdin;  
      Enter data to be copied followed by a newline.  
      End with a backslash and a period on a line by itself.  
      >> 8    'test'  '2017-01-01'  
      >> 9    'test9' '2017-02-02'  
      >> \.  
      COPY 2
    说明

批量更新数据

test03=# UPDATE test SET info=tmp.info from (VALUES (1,'new1'),(2,'new2'),(6,'new6')) AS tmp (id,info) WHERE test.id=tmp.id;  
UPDATE 3  
test03=# SELECT * FROM test;  
 id |     info     |          crt_time            
----+--------------+----------------------------  
  3 | hello        | 2017-04-24 15:31:49.14291  
  4 | digoal0123   | 2017-04-24 15:42:50.912887  
  5 | hello digoal | 2017-04-24 15:57:29.622045  
  1 | new1         | 2017-04-24 15:58:55.610072  
  2 | new2         | 2017-04-24 15:28:20.37392  
  6 | new6         | 2017-04-24 15:59:12.265915  
(6 rows)

批量删除数据

test03=# DELETE FROM test USING (VALUES (3),(4),(5)) AS tmp(id) WHERE test.id=tmp.id;  
DELETE 3  
test03=# SELECT * FROM test;  
 id |  info   |          crt_time            
----+---------+----------------------------  
  1 | new1    | 2017-04-24 15:58:55.610072  
  2 | new2    | 2017-04-24 15:28:20.37392  
  6 | new6    | 2017-04-24 15:59:12.265915

如果要清除全表,建议您使用TRUNCATE。

test03=# SET lock_timeout = '1s';
SET
test03=# TRUNCATE test;  
TRUNCATE TABLE  
test03=# SELECT * FROM test;  
 id | info | crt_time   
----+------+----------  
(0 rows)