使用group vs vs distinct的巨大性能差异
我正在一个包含500 000条目的表在HSQLDB
服务器上执行一些testing。 该表没有索引。 有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
编辑 :我做了额外的testing。 在HSQLDB
有500 000个logging,所有不同的业务密钥, 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
有关。
如果有人能解释为什么会有这么大的差异,我将不胜感激。
这两个查询expression了同样的问题。 查询优化器显然select了两个不同的执行计划。 我的猜测是, distinct
方法是执行如下:
- 将所有
business_key
值复制到临时表 - sorting临时表
- 扫描临时表,返回每个不同于之前的项目
group by
可以被执行,如:
- 扫描整个表,将每个
business key
值存储在散列表中 - 返回哈希表的键
第一种方法优化了内存使用情况:当临时表的一部分必须被交换出来时,仍然能够很好地执行。 第二种方法优化速度,但如果有很多不同的密钥,可能需要大量的内存。
既然你有足够的内存或几个不同的键,第二种方法胜过第一种。 在两个执行计划之间看到10倍甚至100倍的性能差异并不罕见。