그룹 별과 구별을 사용할 때 큰 성능 차이


81

HSQLDB500,000 개의 항목이 포함 된 테이블이 있는 서버 에서 몇 가지 테스트를 수행하고 있습니다. 테이블에 인덱스가 없습니다. 5000 개의 고유 한 비즈니스 키가 있습니다. 목록이 필요합니다. 당연히 나는 DISTINCT쿼리로 시작했습니다 .

SELECT DISTINCT business_key FROM memory WHERE
   concept <> 'case' or 
   attrib <> 'status' or 
   value <> 'closed'

90 초 정도 걸립니다 !!!

그런 다음 사용하려고했습니다 GROUP BY.

SELECT business_key FROM memory WHERE
       concept <> 'case' or 
       attrib <> 'status' or 
       value <> 'closed'
GROUP BY business_key

그리고 1 초가 걸립니다 !!!

내가 실행 한 차이점을 파악하려고 시도 EXLAIN PLAN FOR했지만 두 쿼리에 대해 동일한 정보를 제공하는 것 같습니다.

EXLAIN PLAN FOR DISTINCT ...

isAggregated=[false]
columns=[
  COLUMN: PUBLIC.MEMORY.BUSINESS_KEY
]
[range variable 1
  join type=INNER
  table=MEMORY
  alias=M
  access=FULL SCAN
  condition = [    index=SYS_IDX_SYS_PK_10057_10058
    other condition=[
    OR arg_left=[
     OR arg_left=[
      NOT_EQUAL arg_left=[
       COLUMN: PUBLIC.MEMORY.CONCEPT] arg_right=[
       VALUE = case, TYPE = CHARACTER]] arg_right=[
      NOT_EQUAL arg_left=[
       COLUMN: PUBLIC.MEMORY.ATTRIB] arg_right=[
       VALUE = status, TYPE = CHARACTER]]] arg_right=[
     NOT_EQUAL arg_left=[
      COLUMN: PUBLIC.MEMORY.VALUE] arg_right=[
      VALUE = closed, TYPE = CHARACTER]]]
  ]
]]
PARAMETERS=[]
SUBQUERIES[]
Object References
PUBLIC.MEMORY
PUBLIC.MEMORY.CONCEPT
PUBLIC.MEMORY.ATTRIB
PUBLIC.MEMORY.VALUE
PUBLIC.MEMORY.BUSINESS_KEY
Read Locks
PUBLIC.MEMORY
WriteLocks

EXLAIN PLAN FOR SELECT ... GROUP BY ...

isDistinctSelect=[false]
isGrouped=[true]
isAggregated=[false]
columns=[
  COLUMN: PUBLIC.MEMORY.BUSINESS_KEY
]
[range variable 1
  join type=INNER
  table=MEMORY
  alias=M
  access=FULL SCAN
  condition = [    index=SYS_IDX_SYS_PK_10057_10058
    other condition=[
    OR arg_left=[
     OR arg_left=[
      NOT_EQUAL arg_left=[
       COLUMN: PUBLIC.MEMORY.CONCEPT] arg_right=[
       VALUE = case, TYPE = CHARACTER]] arg_right=[
      NOT_EQUAL arg_left=[
       COLUMN: PUBLIC.MEMORY.ATTRIB] arg_right=[
       VALUE = status, TYPE = CHARACTER]]] arg_right=[
     NOT_EQUAL arg_left=[
      COLUMN: PUBLIC.MEMORY.VALUE] arg_right=[
      VALUE = closed, TYPE = CHARACTER]]]
  ]
]]
groupColumns=[
COLUMN: PUBLIC.MEMORY.BUSINESS_KEY]
PARAMETERS=[]
SUBQUERIES[]
Object References
PUBLIC.MEMORY
PUBLIC.MEMORY.CONCEPT
PUBLIC.MEMORY.ATTRIB
PUBLIC.MEMORY.VALUE
PUBLIC.MEMORY.BUSINESS_KEY
Read Locks
PUBLIC.MEMORY
WriteLocks

편집 : 추가 테스트를 수행했습니다. HSQLDB모든 고유 한 비즈니스 키가 포함 된 500,000 개의 레코드를 사용 하여 DISTINCT이제 성능이 향상되었습니다 ( GROUP BY약 9 초 소요).

에서 MySQL두 쿼리 같은 미리 형성 :

MySQL : 500,000 행-5,000 개의 고유 비즈니스 키 : 두 쿼리 : 0.5 초 MySQL : 500,000 행-모든 고유 비즈니스 키 : SELECT DISTINCT ...-11 초 SELECT ... GROUP BY business_key-13 초

따라서 문제는 HSQLDB.

왜 이렇게 급격한 차이가 있는지 설명해 주시면 감사하겠습니다.


2
결과를 표시하고를 EXPLAIN PLAN실행 한 후 DISTINCT쿼리를 실행하여 GROUP BY캐싱이 타이밍을 왜곡하는지 확인하십시오.
Yahia

각 쿼리에 대해 동일한 계획이 주어지면 테이블 데이터 또는 결과가 캐시 된 것처럼 들립니다.
a'r

캐싱이 문제가되지 않는다고 믿고 여러 번 실행했습니다. EXLAIN PLAN FOR출력을 게시하고 있습니다.
Martin Dimitrov 2011 년

아이디어가 있지만 확실하지 않습니다. 시도해보세요 . 내 아이디어가 옳은 경우 SELECT DISTINCT business_key FROM (SELECT business_key FROM memory WHERE concept <> 'case' or attrib <> 'status' or value <> 'closed')와 동일한 성능을 보여야합니다 GROUP BY.
Yahia

@Yahia : 여전히 매우 느립니다-94 초. 나는 보여줄 것이다 것을 볼 MySQL은 같은 쿼리를 실행
마틴 디미트로프에게

답변:


77

두 쿼리는 동일한 질문을 표현합니다. 분명히 쿼리 최적화 프로그램은 두 가지 실행 계획을 선택합니다. 내 생각에 distinct접근 방식은 다음과 같이 실행됩니다.

  • 모든 business_key값을 임시 테이블에 복사
  • 임시 테이블 정렬
  • 임시 테이블을 스캔하여 이전 테이블과 다른 각 항목을 반환합니다.

다음 group by과 같이 실행할 수 있습니다.

  • 전체 테이블을 스캔하고의 각 값을 business key해시 테이블에 저장 합니다.
  • 해시 테이블의 키 반환

첫 번째 방법은 메모리 사용을 최적화합니다. 임시 테이블의 일부를 교체해야하는 경우에도 여전히 상당히 잘 수행됩니다. 두 번째 방법은 속도를 최적화하지만 다른 키가 많은 경우 잠재적으로 많은 양의 메모리가 필요합니다.

메모리가 충분하거나 다른 키가 적기 때문에 두 번째 방법이 첫 번째 방법보다 성능이 뛰어납니다. 두 실행 계획간에 10 배 또는 100 배의 성능 차이를 보는 것은 드문 일이 아닙니다.


답장을 보내 주셔서 감사합니다. 당신의 추측이 EXPLAIN출력 에서 분명 합니까? 둘 다 나에게 똑같이 보입니다.
Martin Dimitrov 2011 년

내가 볼 수있는 한, 계획은 조인을 실행하는 방법을 지정하지 않습니다. 조인을 실행하는 이유조차 모르겠습니다. Explain 출력을 읽으려면 HSQLDB 전문가가 필요합니다.
Andomar 2011 년

대답에서 알 수 있듯이 두 번째 방법은 더 많은 메모리를 사용하고 GC (가비지 수집)에 너무 자주 도달 할 수 있습니다. JVM 메모리 할당을 늘리면 두 쿼리 시간 사이에 큰 차이가 없어야합니다.
fredt

테이블에 모든 고유 키를 입력하여 추가 테스트를 수행했습니다 (위 참조). 결과가 당신의 요점을 증명한다고 생각하십니까? 감사합니다.
Martin Dimitrov

2
SME- 전문가 예제와 함께 자세한 내용이 설명시겠습니까 ... 나는이 문제에게 여러 번 했어하지만 난 수정 프로그램을 알고 ... 그것을 해결하기 위해 보이지 않는다 그러나 나는 어떻게 그리고 왜 알고 싶다
singhswat
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.