使用group by vs distinct时的巨大性能差异

时间:2011-10-30 08:29:22

标签: sql performance group-by distinct hsqldb

我正在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

修改: 我做了额外的测试。 HSQLDB中包含所有不同业务键的500 000条记录,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 个答案:

答案 0 :(得分:66)

这两个问题表达了同样的问题。显然,查询优化器选择两个不同的执行计划。我的猜测是distinct方法执行如下:

  • 将所有business_key值复制到临时表
  • 对临时表进行排序
  • 扫描临时表,返回与之前不同的项目

group by可以执行如下:

  • 扫描整个表格,将business key的每个值存储在哈希表中
  • 返回哈希表的键

第一种方法优化内存使用:当必须换出部分临时表时,它仍然可以很好地执行。第二种方法优化了速度,但如果存在许多不同的密钥,则可能需要大量内存。

由于你有足够的内存或几个不同的键,第二种方法优于第一种方法。在两个执行计划之间看到10倍甚至100倍的性能差异并不罕见。