PostgreSQL 8.3을 저장소 백엔드 (Python 및 psycopg2 사용)로 사용하는 특정 응용 프로그램이 있습니다. 중요한 테이블에 대해 수행하는 작업은 대부분 삽입 또는 업데이트 (드물게 삭제 또는 선택)입니다.PostgreSQL에서 업데이트/교체 작업의 속도를 높일 수 있습니까?
우리는 합리적으로 잘 작동하는 우리 자신의 Data Mapper과 같은 레이어를 만들었지 만 병목 현상이 많아 업데이트 성능이 떨어졌습니다. 물론, 나는 update/replace 시나리오가 '빈 테이블에 삽입'만큼 빠르다고 기대하지는 않지만 조금 더 가깝게하는 것이 좋을 것입니다. 이 시스템 내 시험에서 단어를 '대체'를 사용하는 용어에서 볼 수있는 우리는 항상 업데이 트에 각 행의 모든 필드를 설정 동시 업데이트
에서 무료입니다
는참고.
업데이트 할 행의 배열을 취하는
replace()
프로 시저를 작성 : 지금까지 우리의 업데이트 문제에 대한 두 가지 접근 방식을 시도했습니다CREATE OR REPLACE FUNCTION replace_item(data item[]) RETURNS VOID AS $$ BEGIN FOR i IN COALESCE(array_lower(data,1),0) .. COALESCE(array_upper(data,1),-1) LOOP UPDATE item SET a0=data[i].a0,a1=data[i].a1,a2=data[i].a2 WHERE key=data[i].key; END LOOP; END; $$ LANGUAGE plpgsql
는
insert_or_replace
규칙을 만듭니다 있도록 모든하지만, 가끔 삭제가된다 다중 행 삽입CREATE RULE "insert_or_replace" AS ON INSERT TO "item" WHERE EXISTS(SELECT 1 FROM item WHERE key=NEW.key) DO INSTEAD (UPDATE item SET a0=NEW.a0,a1=NEW.a1,a2=NEW.a2 WHERE key=NEW.key);
목 모든 테스트는 데이터베이스와 동일한 컴퓨터에서 실행되는
- : 테스트 실행에 대한
Multi-row insert : 50000 items inserted in 1.32 seconds averaging 37807.84 items/s executemany() update : 50000 items updated in 26.67 seconds averaging 1874.57 items/s update_andres : 50000 items updated in 3.84 seconds averaging 13028.51 items/s update_merlin83 (i/d/i) : 50000 items updated in 1.29 seconds averaging 38780.46 items/s update_merlin83 (i/u) : 50000 items updated in 1.24 seconds averaging 40313.28 items/s replace_item() procedure : 50000 items replaced in 3.10 seconds averaging 16151.42 items/s Multi-row insert_or_replace: 50000 items inserted in 2.73 seconds averaging 18296.30 items/s Multi-row insert_or_replace: 50000 items replaced in 2.02 seconds averaging 24729.94 items/s
랜덤 노트 : 후자의 속도가 느려 비트를 삽입하지만, 모두 업데이트 공정한 비트 속도 ESE 상주한다. localhost에 연결 중입니다.
- 삽입 및 업데이트는 각각 500 건의 항목으로 데이터베이스에 적용되며 각 항목은 자체 트랜잭션 (업데이트)으로 전송됩니다.
- 모든 업데이트/바꾸기 테스트는 이미 데이터베이스에있는 것과 동일한 값을 사용했습니다.
- psycopg2 adapt() 기능을 사용하여 모든 데이터가 이스케이프되었습니다.
- 모든 테이블을 절단하고 사용하기 전에 진공 청소기로 청소하다 (만 잘라내는 일이 이전 실행에서, 추가)
표는 다음과 같습니다
CREATE TABLE item ( key MACADDR PRIMARY KEY, a0 VARCHAR, a1 VARCHAR, a2 VARCHAR )
그래서, 진짜 질문은 : 업데이트/교체 작업 속도를 조금 더 높일 수 있습니까? (나는이 결과가 '충분히 좋을 것'이라고 생각하지만, SO 군중을 두드리지 않고 포기하고 싶지는 않다.)
더 우아한 replace_item() 또는 anything을위한 anyones 힌트가있다. 깨진 것이 가장 환영받을 것입니다.
테스트 스크립트는 재현하려는 경우 here을 사용할 수 있습니다. 그래도 그것을 확인하는 것을 잊지 마십시오 ... 그것 WorkForMe,하지만 ...
당신은 DB를 편집해야합니다.설정에 맞게 connect() 행을 사용하십시오. 내가 단일 쿼리 업데이트와 또 다른 시험이는 Freenode @ #postgresql에서 안드레스에
편집
감사합니다; 위의 update_andres로 나열된 다중 행 삽입과 매우 비슷합니다.
UPDATE item
SET a0=i.a0, a1=i.a1, a2=i.a2
FROM (VALUES ('00:00:00:00:00:01', 'v0', 'v1', 'v2'),
('00:00:00:00:00:02', 'v3', 'v4', 'v5'),
...
) AS i(key, a0, a1, a2)
WHERE item.key=i.key::macaddr
편집 내가 삽입 - 투 - 온도와 또 다른 검사를 아래는 Freenode 및 용기/JWP @ #postgresql에서 merlin83에
감사합니다/삭제/삽입 방법 (update_merlin83 "로 표시 (I/d/i) ").
INSERT INTO temp_item (key, a0, a1, a2)
VALUES (
('00:00:00:00:00:01', 'v0', 'v1', 'v2'),
('00:00:00:00:00:02', 'v3', 'v4', 'v5'),
...);
DELETE FROM item
USING temp_item
WHERE item.key=temp_item.key;
INSERT INTO item (key, a0, a1, a2)
SELECT key, a0, a1, a2
FROM temp_item;
내 직감이 시험은 실제 시나리오에서 성능에 매우 대표하지 않습니다,하지만 난 차이가 추가 조사를 위해 가장 유망한 접근법의 표시를 줄만큼 훌륭한 생각이다. perftest.py 스크립트에는 체크 아웃하려는 사용자를위한 모든 업데이트가 포함되어 있습니다. 너무 Freenode의 내가 삽입 - 투 - 온도/업데이트 변형으로 테스트해야한다는 지적 @ (고글 : #postgresql에서
편집
안드레스을 잊지으로 나열되지 않습니다,하지만 매우 추한 "update_merlin83 (i/u)"위).
INSERT INTO temp_item (key, a0, a1, a2)
VALUES (
('00:00:00:00:00:01', 'v0', 'v1', 'v2'),
('00:00:00:00:00:02', 'v3', 'v4', 'v5'),
...);
UPDATE item
SET a0=temp_item.a0, a1=temp_item.a1, a2=temp_item.a2
FROM temp_item
WHERE item.key=temp_item.key
아마 최종 편집 편집 : 는 더 나은 우리의 부하 시나리오에 맞게 내 스크립트를 변경, 그리고 약간의 물건을 확장하고 약간의 임의성을 추가 할 때 번호도 보유 보인다. 누군가 다른 시나리오에서 매우 다른 숫자를 얻는다면 그것에 대해 알고 싶어합니다.
도움이 될? 외국 열쇠? –
테스트 스크립트에는 없습니다. 현실 세계에서, 하나. –
'UPDATE'의'EXPLAIN ANALYZE'를 게시 할 수 있습니까? 나는 평가자가 일어날 것이라고 생각하는 것을 알고 싶다. – Sean