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

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.

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



답변

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

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

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

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

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

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


답변