이 문서는 지원되지 않는 PostgreSQL 버전에 대한 것입니다.
다음에 대한 동일한 페이지를 보고 싶을 수도 있습니다.스포츠 토토 결과3_스포츠 토토 결과SL1검은 색버전 또는 위에 나열된 다른 지원 버전 중 하나를 사용하세요.

40.2. 보기 및 토토 꽁 머니 시스템

다음에서 조회수PostgreSQL토토 꽁 머니 시스템을 사용하여 구현됩니다. 실제로 다음 항목에는 본질적으로 차이가 없습니다.

SELECT * FROM mytab으로 VIEW myview 생성;

두 명령과 비교:

테이블 생성 myview (mytab과 동일한 열 목록);
대신 myview로 선택하여 토토 꽁 머니 "_RETURN"을 생성하세요.
    SELECT * FROM mytab;

이것이 바로 이것이기 때문입니다뷰 만들기명령은 내부적으로 수행됩니다. 여기에는 몇 가지 부작용이 있습니다. 그 중 하나는 뷰에 대한 정보가포스트그레SQL시스템 카탈로그는 테이블의 카탈로그와 정확히 동일합니다. 따라서 파서의 경우 테이블과 뷰 사이에는 전혀 차이가 없습니다. 그것들은 같은 것입니다: 관계.

40.2.1. 어떻게선택토토 꽁 머니 작업

토토 꽁 머니선택 중주어진 명령이 다음과 같더라도 마지막 단계로 모든 쿼리에 적용됩니다.삽입, 업데이트또는삭제. 그리고 새 쿼리 트리를 만드는 대신 쿼리 트리를 수정한다는 점에서 다른 명령 유형의 토토 꽁 머니과 의미 체계가 다릅니다. 그래서선택토토 꽁 머니이 먼저 설명됩니다.

현재는 하나의 작업만 가능합니다.선택 중토토 꽁 머니이며 무조건적이어야 합니다.선택즉 행동은대신. 이 제한은 일반 사용자가 토토 꽁 머니을 열 수 있을 만큼 안전한 토토 꽁 머니을 만드는 데 필요했으며 다음을 제한합니다.선택 중뷰처럼 작동하는 토토 꽁 머니.

이 장의 예는 일부 계산을 수행하는 두 개의 조인 뷰와 이를 차례로 사용하는 추가 뷰입니다. 두 개의 첫 번째 보기 중 하나는 나중에 토토 꽁 머니을 추가하여 사용자 정의됩니다.삽입, 업데이트삭제작업을 수행하여 최종 결과가 일부 마법 기능을 갖춘 실제 테이블처럼 동작하는 뷰가 되도록 합니다. 이것은 시작하기에 그렇게 간단한 예가 아니며 이로 인해 이해하기가 더 어려워집니다. 하지만 혼동될 수 있는 여러 가지 항목을 준비하는 것보다 단계별로 논의된 모든 항목을 다루는 하나의 예시를 갖는 것이 더 좋습니다.

처음 두 토토 꽁 머니 시스템 설명에 필요한 실제 테이블은 다음과 같습니다:

테이블 신발_데이터 생성(
    신발 이름 텍스트, -- 기본 키
    sh_avail 정수, -- 사용 가능한 쌍 수
    slcolor 텍스트, -- 선호하는 신발끈 색상
    slminlen real, -- 최소 신발끈 길이
    slmaxlen real, -- 최대 신발끈 길이
    slunit 텍스트 - 길이 단위
);

CREATE TABLE 신발끈_데이터(
    sl_name text, -- 기본 키
    sl_avail 정수, -- 사용 가능한 쌍 수
    sl_color text, -- 신발끈 색상
    sl_len real, -- 신발끈 길이
    sl_unit 텍스트 -- 길이 단위
);

CREATE TABLE 단위(
    un_name 텍스트, -- 기본 키
    un_fact real -- cm로 변환할 인수
);

보시다시피 신발가게 데이터를 나타냅니다.

뷰는 다음과 같이 생성됩니다:

신발 AS 보기 만들기
    sh.신발이름 선택,
           sh.sh_avail,
           sh.slcolor,
           sh.slminlen,
           sh.slminlen * un.un_fact AS slminlen_cm,
           sh.slmaxlen,
           sh.slmaxlen * un.un_fact AS slmaxlen_cm,
           sh.slunit
      shoe_data sh, 단위 un에서
     sh.slunit = un.un_name;

신발끈 AS 보기 만들기
    s.sl_name 선택,
           s.sl_avail,
           s.sl_color,
           s.sl_len,
           s.sl_유닛,
           s.sl_len * u.un_fact AS sl_len_cm
      신발끈_데이터 s, 단위 u에서
     s.sl_unit = u.un_name;

shoe_ready AS 보기 만들기
    rsh.신발이름 선택,
           rsh.sh_avail,
           rsl.sl_이름,
           rsl.sl_avail,
           최소(rsh.sh_avail, rsl.sl_avail) AS total_avail
      FROM 신발 rsh, 신발끈 rsl
     여기서 rsl.sl_color = rsh.slcolor
       그리고 rsl.sl_len_cm = rsh.slminlen_cm
       그리고 rsl.sl_len_cm <= rsh.slmaxlen_cm;

보기 만들기에 대한 명령신발끈뷰(가장 간단한 뷰)는 관계를 생성합니다신발끈및 다음 항목pg_rewrite관계가 발생할 때마다 적용해야 하는 다시 쓰기 토토 꽁 머니이 있음을 알려줍니다.신발끈은 쿼리의 범위 테이블에서 참조됩니다. 토토 꽁 머니에는 토토 꽁 머니 제한이 없습니다(나중에 논의됨, 비-선택토토 꽁 머니, 이후선택토토 꽁 머니은 현재 이를 가질 수 없습니다) 그리고 그것은대신. 토토 꽁 머니 제한은 쿼리 제한과 동일하지 않습니다. 우리 토토 꽁 머니의 작업에는 쿼리 제한이 있습니다. 토토 꽁 머니의 작업은 다음의 복사본인 하나의 쿼리 트리입니다.선택뷰 생성 명령의 문입니다.

참고

다음에 대한 두 개의 추가 범위 테이블 항목신규그리고오래된당신이 볼 수 있는 것은pg_rewrite다음 항목에 관심이 없습니다.선택토토 꽁 머니.

이제 우리는 채웁니다단위, 신발_데이터그리고신발끈_데이터그리고 뷰에 대해 간단한 쿼리를 실행합니다.

INSERT INTO 단위 VALUES('cm', 1.0);
INSERT INTO 단위 VALUES('m', 100.0);
INSERT INTO 단위 VALUES ('인치', 2.54);

INSERT INTO shoe_data VALUES ('sh1', 2, 'black', 70.0, 90.0, 'cm');
INSERT INTO shoe_data VALUES('sh2', 0, '검은색', 30.0, 40.0, '인치');
INSERT INTO shoe_data VALUES ('sh3', 4, 'brown', 50.0, 65.0, 'cm');
INSERT INTO shoe_data VALUES ('sh4', 3, 'brown', 40.0, 50.0, 'inch');

INSERT INTO shoelace_data VALUES ('sl1', 5, 'black', 80.0, 'cm');
INSERT INTO shoelace_data VALUES ('sl2', 6, 'black', 100.0, 'cm');
INSERT INTO shoelace_data VALUES ('sl3', 0, 'black', 35.0 , 'inch');
INSERT INTO shoelace_data VALUES ('sl4', 8, 'black', 40.0 , 'inch');
INSERT INTO shoelace_data VALUES ('sl5', 4, 'brown', 1.0 , 'm');
INSERT INTO shoelace_data VALUES ('sl6', 0, 'brown', 0.9 , 'm');
INSERT INTO shoelace_data VALUES ('sl7', 7, 'brown', 60 , 'cm');
INSERT INTO shoelace_data VALUES ('sl8', 1, 'brown', 40 , 'inch');

SELECT * 신발끈에서;

 sl_이름 | sl_avail | sl_color | sl_len | sl_유닛 | sl_len_cm
---------+----------+----------+---------+---------+----------
 sl1 |        5 | 검정 |     80 | cm |        80
 sl2 |        6 | 검정 |    100 | cm |       100
 sl7 |        7 | 갈색 |     60 | cm |        60
 sl3 |        0 | 검정 |     35 | 인치 |      88.9
 sl4 |        8 | 검정 |     40 | 인치 |     101.6
 sl8 |        1 | 갈색 |     40 | 인치 |     101.6
 sl5 |        4 | 갈색 |      1 | 남 |       100
 sl6 |        0 | 갈색 |    0.9 | 남 |        90
(8행)

이것이 가장 간단합니다.선택당신은 우리의 뷰에 대해 할 수 있으므로 이 기회에 뷰 토토 꽁 머니의 기본을 설명하겠습니다.SELECT * 신발끈에서파서에 의해 해석되어 쿼리 트리가 생성되었습니다.

SELECT 신발끈.sl_name, 신발끈.sl_avail,
       신발끈.sl_color, 신발끈.sl_len,
       신발끈.sl_unit, 신발끈.sl_len_cm
  신발끈 신발끈에서;

그리고 이것은 토토 꽁 머니 시스템에 제공됩니다. 토토 꽁 머니 시스템은 범위 테이블을 살펴보고 관계에 대한 토토 꽁 머니이 있는지 확인합니다. 에 대한 범위 테이블 항목을 처리할 때신발끈(지금까지 유일한 것) 그것은 다음을 찾습니다_RETURN쿼리 트리를 사용한 토토 꽁 머니:

SELECT s.sl_name, s.sl_avail,
       s.sl_color, s.sl_len, s.sl_unit,
       s.sl_len * u.un_fact AS sl_len_cm
  낡은 신발끈, 새 신발끈,
       신발끈_데이터 s, 단위 u
 s.sl_unit = u.un_name;

보기를 확장하기 위해 재작성은 토토 꽁 머니의 작업 쿼리 트리를 포함하는 하위 쿼리 범위 테이블 항목을 생성하고 보기를 참조한 원래 항목을 이 범위 테이블 항목으로 대체합니다. 결과적으로 다시 작성된 쿼리 트리는 다음을 입력한 것과 거의 동일합니다.

SELECT 신발끈.sl_name, 신발끈.sl_avail,
       신발끈.sl_color, 신발끈.sl_len,
       신발끈.sl_unit, 신발끈.sl_len_cm
  FROM(SELECT s.sl_name,
               s.sl_avail,
               s.sl_color,
               s.sl_len,
               s.sl_유닛,
               s.sl_len * u.un_fact AS sl_len_cm
          신발끈_데이터 s, 단위 u에서
         WHERE s.sl_unit = u.un_name) 신발끈;

그러나 한 가지 차이점이 있습니다: 하위 쿼리의 범위 테이블에는 두 개의 추가 항목이 있습니다.낡은 신발끈그리고새 신발끈. 이러한 항목은 하위 쿼리의 조인 트리 또는 대상 목록에서 참조되지 않으므로 쿼리에 직접 참여하지 않습니다. Rewriter는 이를 사용하여 뷰를 참조한 범위 테이블 항목에 원래 있었던 액세스 권한 확인 정보를 저장합니다. 이러한 방식으로 실행자는 다시 작성된 쿼리에서 뷰를 직접 사용하지 않더라도 사용자에게 뷰에 액세스할 수 있는 적절한 권한이 있는지 확인합니다.

그것이 첫 번째로 적용된 토토 꽁 머니이었습니다. 토토 꽁 머니 시스템은 최상위 쿼리의 나머지 범위 테이블 항목을 계속 확인하고(이 예에서는 더 이상 항목이 없음) 추가된 하위 쿼리의 범위 테이블 항목을 재귀적으로 확인하여 뷰를 참조하는 항목이 있는지 확인합니다. (그러나 확장되지는 않습니다.오래된또는신규— 그렇지 않으면 무한 재귀가 발생합니다!) 이 예에서는에 대한 재작성 토토 꽁 머니이 없습니다.신발끈_데이터또는단위이므로 재작성이 완료되어 위의 내용이 기획자에게 전달되는 최종 결과입니다.

이제 우리는 현재 매장에 있는 어떤 신발에 대해 일치하는 신발끈(색상 및 길이)이 있는지, 정확히 일치하는 쌍의 총 개수가 2보다 크거나 같은지 알아내는 쿼리를 작성하려고 합니다.

SELECT * FROM shoe_ready WHERE total_avail = 2;

 신발이름 | sh_avail | sl_이름 | sl_avail | total_avail
-----------+----------+---------+----------+-------------
 sh1 |        2 | sl1 |        5 |           2
 sh3 |        4 | sl7 |        7 |           4
(2행)

이번 파서의 출력은 쿼리 트리입니다:

SELECT shoe_ready.shoename, shoe_ready.sh_avail,
       shoe_ready.sl_name, shoe_ready.sl_avail,
       shoe_ready.total_avail
  신발 준비 신발 준비에서
 shoe_ready.total_avail = 2;

적용되는 첫 번째 토토 꽁 머니은 다음에 대한 토토 꽁 머니이 될 것입니다.shoe_ready보기 및 쿼리 트리 결과:

SELECT shoe_ready.shoename, shoe_ready.sh_avail,
       shoe_ready.sl_name, shoe_ready.sl_avail,
       shoe_ready.total_avail
  FROM (SELECT rsh.shoename,
               rsh.sh_avail,
               rsl.sl_이름,
               rsl.sl_avail,
               최소(rsh.sh_avail, rsl.sl_avail) AS total_avail
          FROM 신발 rsh, 신발끈 rsl
         여기서 rsl.sl_color = rsh.slcolor
           그리고 rsl.sl_len_cm = rsh.slminlen_cm
           AND rsl.sl_len_cm <= rsh.slmaxlen_cm) shoe_ready
 shoe_ready.total_avail = 2;

마찬가지로 다음 토토 꽁 머니은신발그리고신발끈하위 쿼리의 범위 테이블로 대체되어 3레벨 최종 쿼리 트리로 이어집니다.

SELECT shoe_ready.shoename, shoe_ready.sh_avail,
       shoe_ready.sl_name, shoe_ready.sl_avail,
       shoe_ready.total_avail
  FROM (SELECT rsh.shoename,
               rsh.sh_avail,
               rsl.sl_이름,
               rsl.sl_avail,
               최소(rsh.sh_avail, rsl.sl_avail) AS total_avail
          FROM (SELECT sh.신발이름,
                       sh.sh_avail,
                       sh.slcolor,
                       sh.slminlen,
                       sh.slminlen * un.un_fact AS slminlen_cm,
                       sh.slmaxlen,
                       sh.slmaxlen * un.un_fact AS slmaxlen_cm,
                       sh.slunit
                  shoe_data sh, 단위 un에서
                 sh.slunit = un.un_name) rsh,
               (s.sl_name 선택,
                       s.sl_avail,
                       s.sl_color,
                       s.sl_len,
                       s.sl_유닛,
                       s.sl_len * u.un_fact AS sl_len_cm
                  신발끈_데이터 s, 단위 u에서
                 어디서 s.sl_unit = u.un_name) rsl
         여기서 rsl.sl_color = rsh.slcolor
           그리고 rsl.sl_len_cm = rsh.slminlen_cm
           AND rsl.sl_len_cm <= rsh.slmaxlen_cm) shoe_ready
 shoe_ready.total_avail  2;

이것은 비효율적으로 보일 수 있지만 플래너는 이를 단일 레벨 쿼리 트리로 축소합니다.끌어올리기하위 쿼리를 수행하면 마치 수동으로 작성한 것처럼 조인을 계획할 것입니다. 따라서 쿼리 트리를 축소하는 것은 다시 쓰기 시스템이 걱정할 필요가 없는 최적화입니다.

40.2.2. 비에서 토토 꽁 머니 보기선택문장

질의 트리의 두 가지 세부 사항은 위의 보기 토토 꽁 머니 설명에서 다루어지지 않았습니다. 명령 유형과 결과 관계입니다. 실제로 명령 유형은 뷰 토토 꽁 머니에 필요하지 않지만 결과 관계는 쿼리 재작성기 작동 방식에 영향을 미칠 수 있습니다. 결과 관계가 뷰인 경우 특별한 주의가 필요하기 때문입니다.

a에 대한 쿼리 트리 사이에는 단지 몇 가지 차이점이 있습니다.선택그리고 하나는 다른 명령용입니다. 분명히 그들은 명령 유형이 다르며 a 이외의 명령에 대해SELECT, 결과 관계는 결과가 이동해야 하는 범위 테이블 항목을 가리킵니다. 다른 모든 것은 완전히 동일합니다. 그래서 두 개의 테이블이 있습니다.t1그리고t2열 포함a그리고b, 두 명령문에 대한 쿼리 트리:

t1.a = t2.a인 경우 t1, t2에서 t2.b를 선택하세요.

t1.a = t2.a인 경우 t2에서 t1 세트 b = t2.b 업데이트;

거의 동일합니다. 특히:

  • 범위 테이블에는 테이블에 대한 항목이 포함되어 있습니다.t1그리고t2.

  • 대상 목록에는 열을 가리키는 하나의 변수가 포함되어 있습니다.b테이블에 대한 범위 테이블 항목t2.

  • 한정 표현식은 열을 비교합니다.a동일성을 위한 두 범위 테이블 항목 모두.

  • 조인 트리는 다음 사이의 간단한 조인을 보여줍니다.t1그리고t2.

결과적으로 두 쿼리 트리 모두 유사한 실행 계획이 됩니다. 둘 다 두 테이블에 대한 조인입니다. 에 대한업데이트다음에서 누락된 열t1플래너에 의해 대상 목록에 추가되고 최종 쿼리 트리는 다음과 같이 표시됩니다.

t1.a = t2.a인 t2에서 t1 설정 a = t1.a, b = t2.b 업데이트;

따라서 조인에 대한 실행 프로그램 실행은 다음과 정확히 동일한 결과 세트를 생성합니다.

t1.a = t2.a인 경우 t1, t2에서 t1.a, t2.b를 선택하세요.

하지만 약간의 문제가 있습니다업데이트: 조인을 수행하는 실행기 계획 부분은 조인 결과의 의미를 신경 쓰지 않습니다. 단지 행의 결과 집합을 생성합니다. 하나가 a라는 사실선택명령이고 다른 하나는업데이트이것은 실행기에서 더 높은 수준으로 처리되며, 여기서는 이것이임을 알고 있습니다.업데이트그리고 이 결과가 테이블에 들어가야 한다는 것을 알고 있습니다.t1. 그런데 거기에 있는 행 중 어떤 행을 새 행으로 바꿔야 할까요?

이 문제를 해결하기 위해 다음의 대상 목록에 다른 항목이 추가됩니다.업데이트(또한삭제) 문: 현재 튜플 ID(CTID).이것은 파일 블록 번호와 행의 블록 내 위치를 포함하는 시스템 열입니다. 테이블을 아는 것은,CTID다음의 원래 행을 검색하는 데 사용할 수 있습니다.t1업데이트 예정입니다. 추가한 후CTID대상 목록에 대한 쿼리는 실제로 다음과 같습니다.

t1.a = t2.a인 경우 t1, t2에서 t1.a, t2.b, t1.ctid를 선택하세요.

이제 또 다른 세부사항PostgreSQL무대에 들어갑니다. 이전 테이블 행은 덮어쓰이지 않으며 이것이 바로 이유입니다.롤백빠릅니다. 에서업데이트, 새 결과 행이 테이블에 삽입됩니다(제거한 후CTID) 및 이전 행의 행 헤더에 있는CTID지정된,cmax그리고x최대항목은 현재 명령 카운터와 현재 트랜잭션 ID로 설정됩니다. 따라서 이전 행은 숨겨지고 트랜잭션이 커밋된 후 진공 청소기는 결국 데드 행을 제거할 수 있습니다.

이 모든 것을 알면 우리는 모든 명령에 완전히 동일한 방식으로 보기 토토 꽁 머니을 간단히 적용할 수 있습니다. 차이가 없습니다.

40.2.3. 조회수의 힘포스트그레SQL

위는 토토 꽁 머니 시스템이 원래 쿼리 트리에 보기 정의를 통합하는 방법을 보여줍니다. 두 번째 예에서는 간단한선택하나의 보기에서 4개 테이블의 조인인 최종 쿼리 트리가 생성되었습니다(단위다른 이름으로 두 번 사용되었습니다.)

토토 꽁 머니 시스템으로 보기를 구현하는 이점은 플래너가 스캔해야 하는 테이블에 대한 모든 정보와 이러한 테이블 간의 관계, 보기의 제한적 제한, 단일 쿼리 트리의 원래 쿼리의 제한을 가지고 있다는 것입니다. 그리고 이는 원래 쿼리가 이미 뷰에 대한 조인인 경우에도 마찬가지입니다. 플래너는 쿼리를 실행하는 가장 좋은 경로를 결정해야 하며, 플래너가 더 많은 정보를 갖고 있을수록 더 나은 결정을 내릴 수 있습니다. 그리고 구현된 토토 꽁 머니 시스템은PostgreSQL이것이 해당 시점까지 쿼리에 대해 사용 가능한 모든 정보임을 보장합니다.

40.2.4. 보기 업데이트

뷰가 대상 관계로 명명되면 어떻게 되나요?삽입, 업데이트또는삭제? 위에 설명된 대체를 수행하면 결과 관계가 하위 쿼리 범위 테이블 항목을 가리키는 쿼리 트리가 제공되지만 이는 작동하지 않습니다. 여러 가지 방법이 있습니다.포스트그레SQL그러나 뷰 업데이트 모양을 지원할 수 있습니다.

하위 쿼리가 단일 기본 관계에서 선택되고 충분히 간단한 경우, 재작성은 자동으로 하위 쿼리를 기본 기본 관계로 대체하여 다음이 되도록 할 수 있습니다.삽입, 업데이트또는삭제은 적절한 방식으로 기본 관계에 적용됩니다. 조회수는 다음과 같습니다.충분히 간단함이것은 호출됩니다.자동으로 업데이트 가능. 자동으로 업데이트될 수 있는 뷰 종류에 대한 자세한 내용은 다음을 참조하세요.보기 만들기.

또는 사용자가 제공한 작업을 처리할 수도 있습니다.대신뷰를 트리거합니다. 이 경우 재작성은 약간 다르게 작동합니다. 에 대한삽입, 리라이터는 뷰에 대해 아무 작업도 수행하지 않고 이를 쿼리의 결과 관계로 남겨둡니다. 에 대한업데이트그리고삭제, 여전히 뷰 쿼리를 확장하여오래된명령이 업데이트 또는 삭제를 시도할 행. 따라서 뷰는 정상적으로 확장되지만 확장되지 않은 또 다른 범위 테이블 항목이 쿼리에 추가되어 뷰를 결과 관계로 표현합니다.

이제 발생하는 문제는 뷰에서 업데이트될 행을 식별하는 방법입니다. 결과 관계가 테이블일 때 특수CTID34785_34970CTID, 해당 행에 실제 물리적 위치가 없기 때문입니다. 대신에,업데이트또는삭제작전, 특수전체항목이 대상 목록에 추가되어 보기의 모든 열을 포함하도록 확장됩니다. 실행자는 이 값을 사용하여오래된행에서대신트리거. 이전 행 값과 새 행 값을 기반으로 무엇을 업데이트할지 결정하는 것은 트리거에 달려 있습니다.

또 다른 가능성은 사용자가 정의하는 것입니다.대신대체 작업을 지정하는 토토 꽁 머니삽입, 업데이트삭제뷰에 대한 명령. 이러한 토토 꽁 머니은 일반적으로 뷰가 아닌 하나 이상의 테이블을 업데이트하는 명령으로 명령을 다시 작성합니다. 그것이 주제입니다섹션 40.4.

토토 꽁 머니이 먼저 평가되어 원래 쿼리가 계획되고 실행되기 전에 다시 작성됩니다. 따라서 뷰에 다음이 있는 경우대신트리거 및 토토 꽁 머니삽입, 업데이트, 또는삭제그러면 토토 꽁 머니이 먼저 평가되고 결과에 따라 트리거가 전혀 사용되지 않을 수도 있습니다.

자동 재작성삽입, 업데이트또는삭제단순 보기에 대한 쿼리는 항상 마지막에 시도됩니다. 따라서 보기에 토토 꽁 머니이나 트리거가 있는 경우 자동으로 업데이트 가능한 보기의 기본 동작을 재정의합니다.

없을 경우대신토토 꽁 머니 또는대신뷰에 대한 트리거 및 재작성자가 기본 기본 관계에 대한 업데이트로 쿼리를 자동으로 다시 작성할 수 없습니다. 실행자가 뷰를 업데이트할 수 없기 때문에 오류가 발생합니다.