복붙노트

[SQL] PostgreSQL의에서 병렬 unnest () 및 정렬 순서

SQL

PostgreSQL의에서 병렬 unnest () 및 정렬 순서

그 사용 이해

SELECT unnest(ARRAY[5,3,9]) as id

ORDER BY 절없이, 결과 세트의 순서는 보장되지 않습니다. 나는 예를 들어 얻을 수 있습니다 :

id
--
3
5
9

그러나 다음과 같은 요청에 대해 무엇을 :

SELECT
  unnest(ARRAY[5,3,9]) as id,
  unnest(ARRAY(select generate_series(1, array_length(ARRAY[5,3,9], 1)))) as idx
ORDER BY idx ASC

이 (같은 길이) 2 unnest () 호출이 실제로 배열에있는 항목의 위치를 ​​일치 인덱스 IDX 병렬 것을 풀다 것을 보장인가?

나는 PostgreSQL을 9.3.3을 사용하고 있습니다.

해결법

  1. ==============================

    1.네, 포스트 그레스의 특징이며, (모든 배열은 같은 수의 원소를 가지고만큼) 병렬 unnesting는 동기화로 보장됩니다. 포스트 그레스 9.4 병렬 unnest에 대한 깨끗한 솔루션을 추가합니다 :

    네, 포스트 그레스의 특징이며, (모든 배열은 같은 수의 원소를 가지고만큼) 병렬 unnesting는 동기화로 보장됩니다. 포스트 그레스 9.4 병렬 unnest에 대한 깨끗한 솔루션을 추가합니다 :

    결과 행의 순서는하지만, 보장 할 수 없습니다. 사실, 간단한 같은 문으로 :

    SELECT unnest(ARRAY[5,3,9]) AS id
    

    행의 결과 순서는 "보장"하지만, 포스트 그레스 아무것도 주장하지 않습니다. 그것은 한 순서가 명시 적으로 정의되지 않는 착용감을보고 같이 쿼리 최적화하기 위해 행에게 무료로 제공됩니다. 이것은 더 복잡한 쿼리의 부작용이있을 수 있습니다.

    귀하의 질문에 두 번째 쿼리가 실제로 원하는 경우 generate_subscripts있는 더 좋은 방법은 ()가 (중첩되지 배열 요소에 대한 인덱스 번호를 추가)

    SELECT unnest(ARRAY[5,3,9]) AS id
         , generate_subscripts(ARRAY[5,3,9], 1) AS idx
    ORDER  BY idx;
    

    이 관련 대답 세부 사항 :

    당신은 포스트 그레스 9.4에서 WITH에 순서에 관심이있을 것입니다 :

    그럼 당신은 사용할 수 있습니다 :

    SELECT * FROM unnest(ARRAY[5,3,9]) WITH ORDINALITY tbl(id, idx);
    
  2. ==============================

    2.짧은 답변 : unnest () 출력이 무작위로 주문 될 수 있다는 전제를 수용 할 때 아니오, IDX는, 배열 위치를 일치하지 않습니다.

    짧은 답변 : unnest () 출력이 무작위로 주문 될 수 있다는 전제를 수용 할 때 아니오, IDX는, 배열 위치를 일치하지 않습니다.

    데모: unnest 실제로 출력의 현재 구현 때문에 소자의 순서로 행, I는 임의의 순서를 시뮬레이션 그 위에 층을 추가하도록 제안한다 :

    CREATE FUNCTION unnest_random(anyarray)  RETURNS setof anyelement
    language sql as
    $$ select unnest($1) order by random() $$;
    

    그런 다음 unnest_random로 대체 unnest와 쿼리의 몇 가지 실행을 체크 아웃 :

    SELECT
      unnest_random(ARRAY[5,3,9]) as id,
      unnest_random(ARRAY(select generate_series(1, array_length(ARRAY[5,3,9], 1)))) as idx
    ORDER BY idx ASC
    

    출력의 예 :

     id | idx 
    ----+-----
      3 |   1
      9 |   2
      5 |   3
    

    ID = 3 IDX = 1과 연관되어 있지만,도 3은 어레이의 2 위치에 있었다. 그것은 모든 잘못.

    쿼리에 어떤 문제가 있습니까 : 그것은 처음 unnest가 (: 배열 및 행의 순서로 순서 둘 사이의 관계는 수학적 의미에서 순열) 두 번째 unnest 같은 순열을 사용하여 요소를 셔플 것으로 가정합니다. 그러나이 가정은 unnest의 순서 출력이 시작하기 예측할 수 있다는 전제를 모순.

    이 질문에 대해 :

    선택 unnest (...) X1에서 unnest은 (...) X2는 X1과 X2가 입력 SETOF 무언가의 존재와 동일한 행 수를 갖는, X1 및 X2는 최종 출력에 짝한다 그래서 X1 값 그 행에서 N은 동일한 행에서 N. X2 값을 직면 할 것이다 (카티 제품에 반대는, 열에 대한 UNION의 일종이다).

    그러나 나는 그래서 나는 확실히 이것은 당신이 무엇을 의미입니다 아니에요, 병렬로 풀다으로이 페어링을 설명하지 않을 것입니다.

    unnest 호출이 배열 위치를 잃은 후 문제가 발생하기 때문에 어쨌든이 페어링 문제에 도움이되지 않습니다.

    대안 다음를 pgsql-SQL 메일 링리스트에서이 스레드에서이 기능을 제안한다 :

    CREATE OR REPLACE FUNCTION unnest_with_ordinality(anyarray, OUT value
    anyelement, OUT ordinality integer)
      RETURNS SETOF record AS
    $$
    SELECT $1[i], i FROM
        generate_series(array_lower($1,1),
                        array_upper($1,1)) i;
    $$
    LANGUAGE sql IMMUTABLE; 
    

    이를 바탕으로, 우리는 제 2 출력 컬럼으로 주문할 수있다 :

    select * from unnest_with_ordinality(array[5,3,9]) order by 2;
    
     value | ordinality 
    -------+------------
         5 |          1
         3 |          2
         9 |          3
    

    일반적인 방법으로이 기능을 제공합니다 SET의 반품 함수 호출을 수행 할 수 WITH 순서와 절 : 포스트 그레스 9.4 이상으로.

  3. from https://stackoverflow.com/questions/23830991/parallel-unnest-and-sort-order-in-postgresql by cc-by-sa and MIT license