Огромная разница в производительности при использовании группы против различных


я выполняю некоторые тесты на A HSQLDB сервер с таблицей, содержащей 500 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

EDIT: Я сделал дополнительные тесты. С 500 000 записей HSQLDB со всеми различными бизнес-ключами, производительность DISTINCT теперь лучше - 3 секунды, против GROUP BY, это заняло около 9 секунд.

на MySQL оба запроса имеют одинаковую форму:

MySQL: 500 000 строк - 5 000 различных бизнес-ключей: Оба запроса: 0.5 второй MySQL: 500 000 строк - все отдельные бизнес-ключи: SELECT DISTINCT ... - 11 секунд SELECT ... GROUP BY business_key - 13 секунд

так что проблема только в HSQLDB.

я буду очень благодарен, если кто-то сможет объяснить, почему существует такая резкая разница.

1 58

1 ответ:

два запроса выражают один и тот же вопрос. Очевидно, оптимизатор запросов выбирает два разных плана выполнения. Я предполагаю, что distinct подход выполняется так:

  • скопировать все business_key значения во временную таблицу
  • Сортировать временную таблицу
  • сканируйте временную таблицу, возвращая каждый элемент, отличный от предыдущего

The group by может быть исполнен как:

  • сканирование полная таблица, хранящая каждое значение business key в хеш-таблице
  • верните ключи хэш-таблицы

первый метод оптимизирует использование памяти: он все равно будет работать достаточно хорошо, когда часть временной таблицы должна быть заменена. Второй метод оптимизирует для скорости, но потенциально требует большого объема памяти, если есть много разных ключей.

поскольку у вас либо достаточно памяти, либо несколько разных ключей, второй метод превосходит первый. Это не редкость, чтобы увидеть разницу в производительности 10x или даже 100x между двумя планами выполнения.