2013-04-05 2 views
2

나는 두 배열의 교차 길이를 확인하는 postgresql 쿼리를 가지고있다. 매우 단순화 된 내 쿼리 버전은 다음과 같습니다.heroku에서 intersect를 최적화하는 방법

SELECT array_length(users.array & Array[1,2,3,4]) from users; 

큰 쿼리의 일부이지만 여기서는 중요하지 않습니다. 내 로컬 데이터베이스에서 제대로 작동하지만 heroku에서는 intarray 확장이 허용되지 않습니다.

배열과 교차하는 간단한 함수를 찾았지만 & 연산자와 비교하면 다소 느립니다. & 연산자를 사용하여 내 테이블의 약 2000 기록에

CREATE OR REPLACE FUNCTION array_intersect(anyarray, anyarray) 
RETURNS anyarray AS $$ 
    SELECT ARRAY(SELECT * FROM UNNEST($1) WHERE UNNEST = ANY($2)); 
$$ LANGUAGE sql; 

50ms 및 사용 기능 이상에 대한 150ms 소요됩니다. 최대한 많은 레코드를 비교하고 싶습니다.이 함수는 '&'연산자와 마찬가지로 확장되지 않습니다.

더 빨리 수행하거나 heroku에 intarray를 추가 할 수있는 방법이 있습니까?

답변

1

아마도 쿼리의 나머지 부분에 따라 다르며 최적화가 얼마나 필요한지 추측 할 수 있습니다.

: 필요한 경우

내 첫 번째 시도는 ... 다음 내 주요 표현 내에 CTE의 값을 가져 ... unnestintersect를 사용하여 길이 모든 insecting의 CTE를 만들 수의 라인을 따라 뭔가 될 것

WITH merged AS (
    SELECT * FROM unnest(ARRAY[1,2,3]) 
    INTERSECT 
    SELECT * FROM unnest(ARRAY[1]) 
) 
SELECT count(*) as length FROM merged; 

(내가했던 것처럼)을 사용해 보았을 때 부적절한 경우가 있었지만 그 이후로는 길이에 관심이 있었기 때문에 함수를 반환하여 배열과 다시 불필요한 변환을 피할 수있었습니다. :

CREATE OR REPLACE FUNCTION array_count_intersects(anyarray, anyarray) 
RETURNS bigint AS $$ 
    SELECT count(*) FROM (
     SELECT * FROM UNNEST($1) WHERE UNNEST = ANY($2) 
    ) as merg; 
$$ LANGUAGE sql; 

SELECT array_count_intersects(ARRAY[1,2,3], ARRAY[1]); 

여전히 충분하지 않다면, 데이터를 변경할 때 트리거를 통해 업데이트되는 교차 배열의 길이를 저장/캐시하기위한 중간 테이블을 생성 한 다음이 중간 테이블을 사용하여 길이를 조회합니다. 나는 노동 조합을 전혀 수행 할 필요없이 나의 메인 쿼리에서 필요하다.

+0

의견을 보내 주셔서 감사합니다. 나는 배열 함수를 가지고 있었지만 count 함수를 만들지는 않았다. 나는 heroku에서'&'연산자를 사용하는 방법이 있기를 바랐지만, 나는 이것이 얻을 수있는만큼 가깝다고 생각한다. – Lucas