programing

구체화된 보기를 항상 최신 상태로 유지하려면 어떻게 해야 합니까?

megabox 2023. 6. 18. 12:29
반응형

구체화된 보기를 항상 최신 상태로 유지하려면 어떻게 해야 합니까?

▁to▁i를 호출해야 할 것 같습니다.REFRESH MATERIALIZED VIEW관련된 표를 바꿀 때마다 말이죠, 그렇죠?저는 웹에서 이것에 대한 많은 논의를 발견하지 못해서 놀랐습니다.

어떻게 하면 좋을까요?

제 생각에 여기서 답의 상위 절반은 제가 찾고 있는 것입니다: https://stackoverflow.com/a/23963969/168143

이것에 위험 요소가 있습니까?보기 업데이트가 실패하면 호출 업데이트, 삽입 등의 트랜잭션이 롤백됩니까?(이것이 제가 원하는 것입니다...내 생각엔)

▁to▁i를 호출해야 할 것 같습니다.REFRESH MATERIALIZED VIEW관련된 표를 바꿀 때마다 말이죠, 그렇죠?

네, 포스트그레SQL 자체로는 자동으로 호출되지 않으므로 어떤 방법으로든 SQL을 수행해야 합니다.

어떻게 하면 좋을까요?

이를 달성하기 위한 여러 가지 방법.몇 가지 예를 들기 전에, 명령어는 AccessExclusive 모드에서 보기를 차단하므로 작동하는 동안에는 심지어 할 수도 없습니다.SELECT테이블 위에.

버전 9.4 이상인 경우 다음과 같은 기능을 제공할 수 있습니다.CONCURRENTLY옵션:

REFRESH MATERIALIZED VIEW CONCURRENTLY my_mv;

하며 ExclusiveLock을 차단하지 .SELECT쿼리하지만 오버헤드가 더 클 수 있습니다(변경된 데이터 양에 따라, 변경된 행 수가 적으면 더 빠를 수 있습니다). 두 개를,REFRESH명령을 동시에 실행합니다.

수동으로 새로 고침

그것은 고려해야 할 옵션입니다. 업데이트 후에도 의으로 이루어지는 하게 데이터를 할 수 . 따라서 간단하게 다음을 포함할 수 있습니다.REFRESH마지막에 작전을 수행합니다.

REFRESH 작업

가장 먼저 널리 사용되는 옵션은 예약 시스템을 사용하여 새로 고침을 호출하는 것입니다. 예를 들어 cron 작업에서 다음과 같이 구성할 수 있습니다.

*/30 * * * * psql -d your_database -c "REFRESH MATERIALIZED VIEW CONCURRENTLY my_mv"

그런 다음 30분마다 구체화된 보기가 새로 고쳐집니다.

고려 사항.

이 옵션은 정말 좋습니다, 특히.CONCURRENTLY데이터가 항상 100% 최신 상태가 아님을 허용할 수 있는 경우에만 선택할 수 있습니다.기억하세요, 그것이 있든 없든CONCURRENTLY,REFRESH쿼리를 내부 하는 데 시간을 .REFRESH.

트리거를 사용하여 새로 고침

은 다옵션다호것다입니는출하음을른은▁the다니것입▁another▁to▁call▁is▁option라고 부르는 것입니다.REFRESH MATERIALIZED VIEW다음과 같은 트리거 기능:

CREATE OR REPLACE FUNCTION tg_refresh_my_mv()
RETURNS trigger LANGUAGE plpgsql AS $$
BEGIN
    REFRESH MATERIALIZED VIEW CONCURRENTLY my_mv;
    RETURN NULL;
END;
$$;

그런 다음 보기의 변경사항이 포함된 테이블에서 다음 작업을 수행합니다.

CREATE TRIGGER tg_refresh_my_mv AFTER INSERT OR UPDATE OR DELETE
ON table_name
FOR EACH STATEMENT EXECUTE PROCEDURE tg_refresh_my_mv();

고려 사항.

성능 및 동시성에 대한 몇 가지 중요한 함정이 있습니다.

  1. 모든 INSERT/UPDATE/DELETE 작업은 쿼리를 실행해야 합니다(MV를 고려 중인 경우에는 느릴 수 있음).
  2. 에도.CONCURRENTLY, 둘, 셋.REFRESH여전히 다른 테이블을 차단하므로 관련 테이블의 모든 INSERT/UPDATE/DELETE가 직렬화됩니다.

제가 좋은 생각이라고 생각할 수 있는 유일한 상황은 변화가 정말 드문 경우입니다.

LISTEN/NOTIFY를 사용하여 새로 고침

이전 옵션의 문제는 동기식이며 각 작업에 큰 오버헤드가 발생한다는 것입니다.이를 개선하기 위해 이전과 같은 트리거를 사용할 수 있지만, 이 경우에는 작업만 호출됩니다.

CREATE OR REPLACE FUNCTION tg_refresh_my_mv()
RETURNS trigger LANGUAGE plpgsql AS $$
BEGIN
    NOTIFY refresh_mv, 'my_mv';
    RETURN NULL;
END;
$$;

그런 다음 연결 상태를 유지하고 운영을 사용하여 호출의 필요성을 식별하는 애플리케이션을 구축할 수 있습니다.REFRESH이것을 테스트하는 데 사용할 수 있는 좋은 프로젝트는 pgsidekick이고, 이 프로젝트에서는 셸 스크립트를 사용하여 할 수 있습니다.LISTEN그래서 당신은 예약할 수 있습니다.REFRESH다음과 같이:

pglisten --listen=refresh_mv --print0 | xargs -0 -n1 -I? psql -d your_database -c "REFRESH MATERIALIZED VIEW CONCURRENTLY ?;"

또는 사용pglater 내부(내pgsidekick) REFRESH빈번히예를 들어, 다음 트리거를 사용하여 다음을 수행할 수 있습니다.REFRESH그러나 1분 이내(60초):

CREATE OR REPLACE FUNCTION tg_refresh_my_mv()
RETURNS trigger LANGUAGE plpgsql AS $$
BEGIN
    NOTIFY refresh_mv, '60 REFRESH MATERIALIZED VIEW CONCURRENLTY my_mv';
    RETURN NULL;
END;
$$;

그래서 전화하지 않을 것입니다.REFRESH60초 이내에, 그리고 만약 당신이NOTIFY 번, 60초라는 숫자가 나왔습니다.REFRESH한 번만 트리거됩니다.

고려 사항.

으로, 오래된 데이터로 수 , 은 cron 옵으로서, 이것약데제이오로이, 다다좋만지있니이습같, 이 있습니다.REFRESH는 실제로 필요할 때만 호출되므로 오버헤드가 적고 필요할 때 데이터가 더 가깝게 업데이트됩니다.

OBS: 아직 코드와 예제를 사용해 본 적이 없기 때문에 누군가가 실수를 발견하거나 오타를 내거나 시도하여 작동(또는 작동하지 않는)하면 알려 주십시오.

이제 Postgre가 있습니다.구체화된 보기를 업데이트 상태로 유지하기 위한 SQL 확장: pg_ivm.

내용을 완전히 재계산하지 않고 증분 변경사항만 계산하고 적용합니다.두 가지 접근 방식이 있습니다.IMMEDIATE그리고.DEFERRED:

  • 위해서IMMEDIATE뷰는 기본 테이블이 수정된 것과 동일한 트랜잭션에서 업데이트됩니다.

  • 위해서DEFERRED트랜잭션이 커밋된 후 보기가 업데이트됩니다.

버전 1.0은 2022-04-28에 출시되었습니다.

마테우스 올의 이전 답변에서 세 가지를 지적하겠습니다. 바로 pglater 기술입니다.

  1. long_interval 배열의 마지막 요소로 "배열의 마지막 요소는 0으로 채워야 합니다."라는 문구로 https://linux.die.net/man/3/getopt_long 에서 가리키는 "{0, 0, 0, 0, 0}" 요소를 포함해야 합니다.그래서, 그것은 -라고 쓰여질 것입니다.

    static struct option long_options[] =     {
          //......
          {"help", no_argument, NULL, '?'},
          {0, 0, 0, 0} 
    };
    
  2. malloc/free에서 -- 하나의 free(char listen = malloc(...;)가 누락되었습니다. 어쨌든, malloc은 CentOS에서 pglater 프로세스를 중단시켰습니다(Ubuntu는 아니지만 - 이유는 모르겠습니다). 따라서 char 배열을 사용하고 배열 이름을 char 포인터(char 및 char** 모두에 할당)에 할당하는 것이 좋습니다.이 작업(포인터 할당)을 수행하는 동안 유형을 강제로 변환해야 하는 경우가 많습니다.

    char block4[100];
    ...
    password_prompt = block4;
    ...
    char block1[500];
    const char **keywords = (const char **)&block1;
    ...
    char block3[300];
    char *listen = block3;
    sprintf(listen, "listen %s", id);
    PQfreemem(id);
    res = PQexec(db, listen);
    
  3. 아래 표를 사용하여 md가 mediate_duration인 타임아웃을 계산합니다. 여기서 md는 최신 새로 고침(lr) 시점과 현재 시간 사이의 시간 차이입니다.

    md > == callback_mdk(cd) => 시간 초과: 0

    md + PING_INTERVAL > == cd => 시간 초과: cd-md[=cd-(now-lr)]

    md + PING_INTERVAL < cd ==> 시간 초과 시: PI

이 알고리즘(3번째 포인트)을 구현하려면 다음과 같이 'lr'을 시작해야 합니다.

res = PQexec(db, command);
latest_refresh = time(0);
if (PQresultStatus(res) == PGRES_COMMAND_OK) {

언급URL : https://stackoverflow.com/questions/29437650/how-can-i-ensure-that-a-materialized-view-is-always-up-to-date

반응형