2017-05-22 3 views
0

을 숨 깁니다 전에 내가이 훌륭하게 작동포스트 그레스 트리거는 인덱스를 생성합니다 INSERT ON 한 행을

CREATE OR REPLACE FUNCTION myfunction() RETURNS trigger AS 
$BODY$ 
    DECLARE 
     index TEXT; 
    BEGIN 
     index := 'myIndex_' || NEW.id2::text; 
     IF to_regclass(index::cstring) IS NULL THEN 
      EXECUTE 'CREATE INDEX ' || index || ' ON mytable(id) WITH (FILLFACTOR=100) WHERE id2=' || NEW.id2|| ';'; 
      RAISE NOTICE 'Created new index %',index; 
     END IF; 
     RETURN NULL; 
    END; 
$BODY$ 
LANGUAGE plpgsql VOLATILE 
SECURITY DEFINER 
COST 100; 
ALTER FUNCTION myfunction() 
    OWNER TO theadmin; 

함수를 호출하는 트리거 AFTER INSERT ON mytable 있습니다. 각 고유 문자에 대해 id2 색인을 만듭니다. 관련 검색어를 많이 늘립니다.

위에서 언급 한 바와 같이 나는 AFTER INSERT ON을 트리거합니다. 그러나 그 전에 트리거를 BEFORE INSERT ON으로 설정했습니다. 그리고이 기능은 이상한 일을했습니다. insert into mytable VALUES(1391, 868, 0.5, 0.5);

  • 은 선택을 할 때 삽입 된 행 는 MYTABLE에 나타나지 않습니다 해당 인덱스 myIndex_868
  • 를 생성하는 새 행의

    • 삽입 (네, RETURN NULLRETURN NEW로 변경했다) :(
    • 같은 행을 넣으려고하면 ERROR: duplicate key value violates unique constraint "mytable_pkey"이됩니다. 물론 DETAIL: Key (id, id2)=(1391, 868) already exists.
    • 다른 행을 삽입해야합니다. 전자 같은 ID2는 예상대로 작동 :
    • DELETE FROM mytable WHERE id = 1391 and id2 = 868
    • DROP INDEX myIndex_868; 색인을 삭제 아무것도를하지 않습니다. 그리고 갑자기 테이블에 나타나지 않은 초기 행이 갑자기 나타납니다!

    BEFORE INSERT ON은 다르게 동작합니까? 이것은 postgres 9.4의 버그입니까, 아니면 뭔가 간과 했나요?

    그냥 완전성 '을 위해 :

    CREATE TRIGGER mytrigger 
    AFTER INSERT ON mytable 
    FOR EACH ROW EXECUTE PROCEDURE myfunction(); 
    

    CREATE TRIGGER mytrigger 
    BEFORE INSERT ON mytable 
    FOR EACH ROW EXECUTE PROCEDURE myfunction(); 
    
  • 답변

    2

    나는 이것이 PostgreSQL의 버그이라고 주장 것입니다. 9.6으로 재현 할 수 있습니다.

    트리거가 BEFORE 트리거에서 생성 될 때 행에 색인이 포함되어 있지 않지만 행이 삽입 될 때 색인이 업데이트되지 않는다는 것이 분명합니다.

    나는 의견을 요구하기 위하여 written to pgsql-hackers가있다.

    그러나 그렇다고해서 나는 전체 운동의 요점을 보지 못했습니다. gazillion 인덱스를 만드는 것보다 더 나은 작성하는 것 하나 하나 :

    CREATE INDEX ON mytable(id2, id); 
    
    +0

    그 커버 ID2에 대한 내 모든 쿼리는'MYTABLE SELECT * FROM 것 WHERE ID2 = $ 1 '인덱스와 지금, 매우 느린로 사용? 각 WHERE 절은 빠릅니다. – bodison

    +1

    그 때문에 더 간단한 인덱스가 더 좋을 것입니다 : CREATE INDEX ON mytable (id2)'. –

    +0

    정말이에요? WHERE 절당 하나의 인덱스가 필요하다는 인상하에있었습니다. 또한 이드의 결과를 정렬하고 있습니다. 'SELECT * FROM mytable where id2 = $ 1 ORDER BY id; '그리고 인덱스는 그 속도를 엄청나게 향상시킵니다. – bodison