Огромная разница в производительности при использовании группы против различных
я выполняю некоторые тесты на 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 ответ:
два запроса выражают один и тот же вопрос. Очевидно, оптимизатор запросов выбирает два разных плана выполнения. Я предполагаю, что
distinctподход выполняется так:
- скопировать все
business_keyзначения во временную таблицу- Сортировать временную таблицу
- сканируйте временную таблицу, возвращая каждый элемент, отличный от предыдущего
The
group byможет быть исполнен как:
- сканирование полная таблица, хранящая каждое значение
business keyв хеш-таблице- верните ключи хэш-таблицы
первый метод оптимизирует использование памяти: он все равно будет работать достаточно хорошо, когда часть временной таблицы должна быть заменена. Второй метод оптимизирует для скорости, но потенциально требует большого объема памяти, если есть много разных ключей.
поскольку у вас либо достаточно памяти, либо несколько разных ключей, второй метод превосходит первый. Это не редкость, чтобы увидеть разницу в производительности 10x или даже 100x между двумя планами выполнения.