繁体   English   中英

PostgreSQL LOGGED和UNLOGGED表性能与LOCK TABLE的使用比较

[英]PostgreSQL LOGGED and UNLOGGED table performance comparison with LOCK TABLE usage

我正在尝试在PostgreSQL(10.3)中的LOGGEDUNLOGGED表上测量UPDATE速度。 我想使用LOCK TABLE来防止其他应用程序相互干扰。

如果在不使用LOCK TABLE情况下执行UPDATE ,则LOGGED表为UNLOGGED表为UNLOGGED

如果使用LOCK TABLE执行UPDATE ,则两种表类型的结果都相同。

为什么在两种表类型中LOCK TABLE返回相同的结果?

我的PL / pgSQL函数:

CREATE OR REPLACE FUNCTION public.myfunction(user_id integer, unitprice numeric(10,6), 
            islock boolean, useunlogged boolean) RETURNS integer AS
$BODY$
declare howMuch integer;
begin       
    if islock then
        if useunlogged then 
            LOCK TABLE credittable_unlogged IN ACCESS EXCLUSIVE MODE;
        else
            LOCK TABLE credittable IN ACCESS EXCLUSIVE MODE;
        end if;
    end if;
    if useunlogged then     
        select (credit_amount/unitprice)::integer into howMuch from credittable where userid=user_id and credit_amount>=unitprice;
        if howMuch is null then 
            select 0 into howMuch;
        else
            update credittable set credit_amount=credit_amount-unitprice where userid=user_id;
        end if;    
    else 
        select (credit_amount/unitprice)::integer into howMuch from credittable_unlogged where userid=user_id and credit_amount>=unitprice;
        if howMuch is null then 
           select 0 into howMuch;
        else
            update credittable_unlogged set credit_amount=credit_amount-unitprice where userid=user_id;
        end if;  
    end if;
    RETURN howMuch;
 end;
 $BODY$
   LANGUAGE plpgsql VOLATILE
    COST 100;
 ALTER FUNCTION public.myfunction(integer, numeric, boolean, boolean)
    OWNER TO postgres;

我的Java代码:

for(int i=1;i<=4;i++){
    long startTime = System.nanoTime();
    int counter = 0;        
    while ((System.nanoTime() - startTime) < 1000000000L) {
        CallableStatement callst = null;
        try {
            String sql = "{? = call public.myfunction(?,?,?,?) }";
            callst = con.prepareCall(sql);
            callst.registerOutParameter(1, Types.INTEGER);
            callst.setInt(2, 123456);
            callst.setBoolean(3, (i > 2));
            callst.setBoolean(4, (i%2 != 0));
            callst.setBigDecimal(3, BigDecimal.valueOf(0.001));
            callst.execute();
            int howMuch = callst.getInt(1);                
            counter++;                
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            if (callst != null) {
                callst.close();
            }
        }
    }
    System.out.println("Counter :"+counter);
}   

您在此处测量的很多内容是客户端服务器延迟和PL / pgSQL执行。

造成这种差异的原因是必须将WAL同步到磁盘。

如果使用未记录的表,并且不使用LOCK语句,则不会写入WAL,并且在COMMIT时无需同步任何内容。

显式表锁导致写入WAL记录,因此COMMIT仍然必须同步WAL,并且您将失去从未记录表中获得的优势。

您可以使用pg_waldump检查WAL文件,然后您将看到写入了哪些事务日志记录。

但是我可以使用-DWAL_DEBUG构建的PostgreSQL v11向您-DWAL_DEBUG

这是我的测试表:

postgres=# \d t
             Unlogged table "public.t"
 Column |  Type   | Collation | Nullable | Default 
--------+---------+-----------+----------+---------
 id     | integer |           |          | 

这里是没有LOCK TABLEINSERT

postgres=# SET wal_debug=on;
SET
postgres=# BEGIN;
BEGIN
postgres=# INSERT INTO t VALUES (100);
INSERT 0 1
postgres=# COMMIT;
LOG:  INSERT @ 0/166BFB8:  - Transaction/COMMIT: 2018-05-18 20:34:20.060635+02
STATEMENT:  COMMIT;
COMMIT

有一个提交,但没有WAL刷新。

postgres=# BEGIN;
BEGIN
postgres=# LOCK TABLE t;
LOG:  INSERT @ 0/166C038:  - Standby/LOCK: xid 569 db 13344 rel 16384 
STATEMENT:  LOCK TABLE t;
LOCK TABLE
postgres=# INSERT INTO t VALUES (101);
INSERT 0 1
postgres=# COMMIT;
LOG:  INSERT @ 0/166C138:  - Transaction/COMMIT: 2018-05-18 20:36:15.419081+02
STATEMENT:  COMMIT;
LOG:  xlog flush request 0/166C138; write 0/166BFF0; flush 0/166BFF0
STATEMENT:  COMMIT;
COMMIT

现在我们有了WAL刷新,这是昂贵的部分。

您会看到一个Standby/LOCK记录已写入。

解决该问题的一种方法是将wal_level减小为minimal ,将max_wal_senders0 ,然后不必写入这些WAL记录。 但是,您将无法进行WAL归档和时间点恢复。

另一个解决方法是使用比ACCESS EXCLUSIVE更低的锁定级别。 除非您绝对必须阻止读者,否则应该没问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM