[英]PostgreSQL LOGGED and UNLOGGED table performance comparison with LOCK TABLE usage
我正在嘗試在PostgreSQL(10.3)中的LOGGED
和UNLOGGED
表上測量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 TABLE
的INSERT
:
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_senders
為0
,然后不必寫入這些WAL記錄。 但是,您將無法進行WAL歸檔和時間點恢復。
另一個解決方法是使用比ACCESS EXCLUSIVE
更低的鎖定級別。 除非您絕對必須阻止讀者,否則應該沒問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.