2011-05-03 3 views
4

저는 미국에서의 태양 잠재력을 나타내는 비영리 단체와 협력하고 있습니다. 말할 필요도없이, 우리는 엄청나게 큰 PostgreSQL 9 데이터베이스를 가지고 있습니다. 아래 표시된 것과 같은 쿼리를 실행하면 order by 행의 주석 처리가 해제 될 때까지 속도가 빨라집니다.이 경우 동일한 쿼리가 영원히 실행됩니다 (25 분에 비해 정렬없이 185ms). 이 쿼리와 다른 쿼리를보다 관리하기 쉽고 합리적인 시간에 실행하려면 어떤 단계를 수행해야합니까?ORDER BY를 사용하면 DB 성능이 좋지 않음

select A.s_oid, A.s_id, A.area_acre, A.power_peak, A.nearby_city, A.solar_total 
from global_site A cross join na_utility_line B 
where (A.power_peak between 1.0 AND 100.0) 
and A.area_acre >= 500 
and A.solar_avg >= 5.0 
AND A.pc_num <= 1000 
and (A.fips_level1 = '06' AND A.fips_country = 'US' AND A.fips_level2 = '025') 
and B.volt_mn_kv >= 69 
and B.fips_code like '%US06%' 
and B.status = 'active' 
and ST_within(ST_Centroid(A.wkb_geometry), ST_Buffer((B.wkb_geometry), 1000)) 
--order by A.area_acre 
offset 0 limit 11; 
+2

쿼리에서 얼마나 많은 행을 반환합니까? 각각의 경우에 EXPLAIN ANALYZE를 통해 쿼리를 실행할 때 출력은 무엇입니까? –

+2

문제를 해결하는 첫 번째 단계는 * 두 버전의 쿼리에 대한 explain analyze 출력을 살펴 보는 것입니다. 당신이 그것을 읽을 수 없다면 (아주 ​​친숙하지는 않습니다) http://explain.depesz.com/에 올려 놓고 두 계획에 대한 링크를주십시오. –

+0

이 특정 쿼리의 결과는 11 행뿐입니다. '주문 기준'이없는 Explain Analyze의 출력은 WITH 정렬과 기본적으로 동일하며 행을 정렬하는 데 사용 된 117117ms를 뺀 값입니다. –

답변

5

정렬은 문제가되지 않습니다. 사실 Postgres에는 결과 집합이 검색되는 곳의 Top-N 정렬이 있기 때문에 정렬의 CPU와 메모리 비용은 0에 가깝습니다. 상위 N 개의 행.

select count(*) from (1 million row table)    -- 0.17 s 
select * from (1 million row table) order by x limit 10; -- 0.18 s 
select * from (1 million row table) order by x;   -- 1.80 s 

그래서 당신은 최고 10 만 실제 종류에 대한 더 많은 대 바보 빠른 카운트 (*) 10 밀리 추가 정렬을 참조하십시오. 그건 아주 청초한 기능입니다. 많이 사용합니다.

이제는 EXPLAIN ANALYZE 없이는 확신 할 수 없지만 실제로는 크로스 조인이라고 생각합니다. 기본적으로 두 테이블의 행을 다음과 같이 필터링합니다.

where (A.power_peak between 1.0 AND 100.0) 
and A.area_acre >= 500 
and A.solar_avg >= 5.0 
AND A.pc_num <= 1000 
and (A.fips_level1 = '06' AND A.fips_country = 'US' AND A.fips_level2 = '025') 

and B.volt_mn_kv >= 69 
and B.fips_code like '%US06%' 
and B.status = 'active' 

OK. 두 테이블 모두에서 얼마나 많은 행이 선택되었는지는 알지 못합니다 (EXPLAIN ANALYZE 만 알려줄 것입니다).하지만 중요한 것 같습니다. 그 숫자를 안다면 도움이 될 것입니다. 이것은 (그래서,이 표현은 시대의 큰 숫자를 평가하는 것입니다 B의 모든 행에 대해 일치되는 모든 행을 의미

and ST_within(ST_Centroid(A.wkb_geometry), ST_Buffer((B.wkb_geometry), 1000)) 

:

그런 다음 우리는 최악의 경우 CROSS 적 조건 가입있어), 꽤 복잡하고 느리고 CPU 집약적 인 기능을 사용합니다.

물론 끔찍하게 느립니다!

ORDER BY를 제거하면 postgres가 LIMIT에 도달 한 이후 처음부터 일치하는 행을 묶어서 출력하고 출력하며 중지합니다. A와 B가 동일한 1000 개 행을 포함

테이블 및 BOX 형 컬럼 :

여기 작은 예이다. 여기 1,000,000 상자 오버랩 (운영자 & &)

select * from a cross join b where (a.b && b.b)  --- 0.28 s 

은 0.28s 시험은 완료된다. 테스트 데이터 세트는 결과 세트가 단지 1000 개의 행을 포함하도록 생성됩니다.

create index a_b on a using gist(b); 
create index b_b on a using gist(b); 
select * from a cross join b where (a.b && b.b)  --- 0.01 s 

여기에서 색인은 교차 결합을 최적화하는 데 사용되며 속도는 터무니 없습니다.

해당 지오메트리를 최적화해야합니다.

  • ST_Centroid (A.wkb_geometry)
  • 에는 ST_Buffer ((B.wkb_geometry), 1000) 재 계산 의미가 없습니다

:

  • 는 캐시합니다 열을 추가 CROSS JOIN 동안 천천히 기능하는 경우가 있으므로 결과를 열에 저장하십시오. 트리거를 사용하여 최신 상태로 유지하십시오.

    • 것은 캐시합니다 형 BOX의 열을 추가 :

        ST_Centroid의
      • 경계 상자 (A.wkb_geometry)
      • 에는 ST_Buffer의
      • 경계 상자 ((B.wkb_geometry), 1000)
    • 이 상자에 요점 인덱스를 추가

    • 상자 비켜 추가 패스 행에 대한 최종 필터 역할을 계속하여 ST_Within에를

    • 를 인덱스를 사용합니다 (& & 연산자를 사용하여) rlap 시험

    어쩌면 당신이 할 수있는 단지 인덱스 ST_Centroid과에는 ST_Buffer

    http://www.postgresql.org/docs/8.2/static/functions-geometry.html

+0

감사합니다. 덕분에 많은 도움이되었습니다. –

+0

감사합니다;) 성능 문제를 해결할 수 있습니까? – peufeu

+0

표현식에 대한 색인, 누구입니까? :-) http://stackoverflow.com/a/22690775/618649 – Craig

0

먼저 색인을 생성하고, db가 비우는 지 확인하고, db 설치, work_mem 설정을위한 공유 버퍼를 늘리십시오.

2

나는 area_acre에 대한 색인을 만드는 것이 좋습니다. 다음을 살펴보아야 할 수도 있습니다. http://www.postgresql.org/docs/9.0/static/sql-createindex.html

많은 양의 데이터가 집중 될 수 있기 때문에 피크 시간대에 이런 일을하는 것이 좋습니다. 색인으로보아야 할 한 가지 사항은 시간이 지남에 따라 성능을 보장하기 위해 일정에 따라 rebuilding입니다. 다시이 일정은 피크 시간 바깥에 있어야합니다.

당신은 동료 SO'er에서이 문서의 모양과 인덱스 시간이 지남에 따라 데이터베이스 성능 저하와 자신의 경험을 할 수 있습니다 : Why does PostgresQL query performance drop over time, but restored when rebuilding index 당신은 필드에 인덱스가 있는지 여부를

+0

해당 테이블은 이미 인덱스 화되어 있습니다. CREATE INDEX global_site_area_acre_idx ON global_site USING btree (area_acre DESC); - 더 좋은 방법이 있습니까? –

+0

이러한 색인에 DESC를 사용하는 것은 중요하지 않습니다. –

0
보는

우선이다 당신이 주문하고 있습니다. 그렇지 않은 경우 성능을 크게 향상시킬 수 있습니다. 다른 답변에서 언급 한 바와 같이 큰 데이터 세트로 작업 할 때, 인덱싱 프로세스는 많이 사용

CREATE INDEX area_acre ON global_site(area_acre) 

, 그래서 오프 피크 동안이 작업을 수행 : 나는에 잘 PostgreSQL을하지만 비슷한 모른다.

+0

해당 필드는 실제로 인덱싱됩니다. 인덱싱은'CREATE INDEX global_site_area_acre_idx ON global_site USING btree (area_acre DESC);'와 같이 수행되었습니다. 이것에 문제가 있습니까? 그리고/또는 그것을 조정할 수 있습니까? –

1

A.area_acre 필드가 인덱싱되지 않아 속도가 느려질 수 있습니다. EXPLAIN을 사용하여 쿼리를 실행하면 실행 중에 수행중인 작업을 확인할 수 있습니다.

0

PostgreSQL 최적화에 익숙하지 않지만 ORDER BY 절을 사용하여 쿼리를 실행하면 전체 결과 집합이 만들어진 다음 정렬되어 상위 11 개 행 정렬 된 결과에서 가져옵니다. ORDER BY가 없으면 쿼리 엔진은 원하는 순서대로 처음 11 개의 행을 생성 한 다음 완료합니다.

area_acre 필드의 색인을 사용하면 결과 집합의 작성 방법에 따라 정렬 (ORDER BY)에 도움이되지 않을 수 있습니다. 이론적으로는 area_acre의 인덱스를 사용하여 global_site 테이블을 탐색하여 결과 집합을 생성하는 데 사용할 수 있습니다. 이 경우 결과는 원하는 순서대로 생성됩니다 (결과에 11 개의 행을 생성 한 후 중지 될 수 있음). 그 순서대로 결과를 생성하지 않으면 (그리고 그렇지 않을 수도 있습니다), 그 색인은 결과를 정렬하는 데 도움이되지 않습니다.

"CROSS JOIN"을 쿼리에서 제거하는 것이 좋습니다. 나는 이것이 차이를 만들지는 모르겠지만, 시험할만한 가치가있다. WHERE 절이 ST_WITHIN을 통해 두 테이블을 결합하는 것이기 때문에 결과는 내부 조인과 동일하다고 생각합니다. CROSS JOIN 구.을 사용하면 옵티마이 저가 원하지 않는 선택을하게 될 수 있습니다.

그렇지 않으면 (필터링되는 필드에 대한 인덱스가 있는지 확인하는 것 외에는) 쿼리로 약간의 추측 게임을 할 수 있습니다. 눈에 띄는 조건 중 하나는 area_acre >= 500입니다. 이는 쿼리 엔진이 해당 조건을 충족시키는 모든 행을 고려하고 있음을 의미합니다.그러나 처음 11 행만이 사용됩니다. 그것을 area_acre >= 500 and area_acre <= somevalue으로 변경해보십시오. somevalue은 적어도 11 개의 행을 확보하기 위해 조정해야 할 추측 부분입니다. 이것은, 그러나, 꽤 사소한 일을하는 것처럼 보입니다, 그래서 나는 그것을 과묵하게 언급합니다.

0

당신이 이익을 위해 Expression based indexes을 만드는 것으로 간주 유무 : 열 ... 그리고는 "포함"(인덱스) 연산자 여기를 참조 사용 더 털이 많은 조인 중 어디에 조건이 있니?

관련 문제