Я провожу несколько тестов на 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 строк - 5000 отдельных бизнес-ключей: Оба запроса: 0,5 секунды MySQL: 500 000 строк - все отдельные бизнес-ключи:
SELECT DISTINCT ...
- 11 секунд
SELECT ... GROUP BY business_key
- 13 секунд
Так что проблема связана только с HSQLDB
.
Буду очень признателен, если кто-нибудь сможет объяснить, почему такая резкая разница.
EXPLAIN PLAN
И попробуйтеDISTINCT
выполнить запрос ПОСЛЕ того, как вы запустите,GROUP BY
чтобы увидеть, возможно, некоторое кеширование искажает время ...EXLAIN PLAN FOR
вывод.SELECT DISTINCT business_key FROM (SELECT business_key FROM memory WHERE concept <> 'case' or attrib <> 'status' or value <> 'closed')
- это должно показать ту же производительность, которую вы видите сGROUP BY
ЕСЛИ моя идея верна.Ответы:
Два запроса выражают один и тот же вопрос. Очевидно, оптимизатор запросов выбирает два разных плана выполнения. Я предполагаю, что
distinct
подход выполняется так:business_key
значения во временную таблицуgroup by
Может быть выполнен как:business key
в хеш-Первый метод оптимизирует использование памяти: он все равно будет работать достаточно хорошо, когда необходимо выгрузить часть временной таблицы. Второй метод оптимизирует скорость, но потенциально требует большого объема памяти, если имеется много разных ключей.
Поскольку у вас либо достаточно памяти, либо несколько разных ключей, второй метод превосходит первый. Нередко можно увидеть разницу в производительности в 10 или даже 100 раз между двумя планами выполнения.
источник
EXPLAIN
вывода? Оба кажутся мне одинаковыми.