구체화된 보기를 항상 최신 상태로 유지하려면 어떻게 해야 합니까?
▁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();
고려 사항.
성능 및 동시성에 대한 몇 가지 중요한 함정이 있습니다.
- 모든 INSERT/UPDATE/DELETE 작업은 쿼리를 실행해야 합니다(MV를 고려 중인 경우에는 느릴 수 있음).
- 에도.
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;
$$;
그래서 전화하지 않을 것입니다.REFRESH
60초 이내에, 그리고 만약 당신이NOTIFY
번, 60초라는 숫자가 나왔습니다.REFRESH
한 번만 트리거됩니다.
고려 사항.
으로, 오래된 데이터로 수 , 은 cron 옵으로서, 이것약데제이오로이, 다다좋만지있니이습같, 이 있습니다.REFRESH
는 실제로 필요할 때만 호출되므로 오버헤드가 적고 필요할 때 데이터가 더 가깝게 업데이트됩니다.
OBS: 아직 코드와 예제를 사용해 본 적이 없기 때문에 누군가가 실수를 발견하거나 오타를 내거나 시도하여 작동(또는 작동하지 않는)하면 알려 주십시오.
이제 Postgre가 있습니다.구체화된 보기를 업데이트 상태로 유지하기 위한 SQL 확장: pg_ivm.
내용을 완전히 재계산하지 않고 증분 변경사항만 계산하고 적용합니다.두 가지 접근 방식이 있습니다.IMMEDIATE
그리고.DEFERRED
:
위해서
IMMEDIATE
뷰는 기본 테이블이 수정된 것과 동일한 트랜잭션에서 업데이트됩니다.위해서
DEFERRED
트랜잭션이 커밋된 후 보기가 업데이트됩니다.
마테우스 올의 이전 답변에서 세 가지를 지적하겠습니다. 바로 pglater 기술입니다.
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} };
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);
아래 표를 사용하여 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
'programing' 카테고리의 다른 글
스토어 게터를 기준으로 조건부로 b-테이블 열 표시/숨기기 (0) | 2023.06.18 |
---|---|
Excel에서 대문자 분할 (0) | 2023.06.18 |
C - time_t를 YYY-MM-DD 형식의 문자열로 변환 HH:MM:SS (0) | 2023.06.18 |
C: 간격으로 플로트를 감는 방법 [-pi, pi) (0) | 2023.06.18 |
typeScript의 array.groupBy (0) | 2023.06.18 |