Огромная разница в производительности при использовании группы по отдельным - PullRequest
66 голосов
/ 30 октября 2011

Я выполняю некоторые тесты на сервере 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

РЕДАКТИРОВАТЬ : я провел дополнительные тесты.С 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 Ответ

66 голосов
/ 30 октября 2011

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

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

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

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

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

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

...