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

Mar*_*rov 71 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'
Run Code Online (Sandbox Code Playgroud)

大约需要90秒!

然后我尝试使用GROUP BY:

SELECT business_key FROM memory WHERE
       concept <> 'case' or 
       attrib <> 'status' or 
       value <> 'closed'
GROUP BY business_key
Run Code Online (Sandbox Code Playgroud)

它需要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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

编辑:我做了额外的测试.拥有HSQLDB所有不同业务键的50万条记录,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.

如果有人能解释为什么会有这么大的差异,我将非常感激.

And*_*mar 69

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

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

group by可以执行这样的:

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

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

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

  • 中小企业专家能否通过实例更详细地解释一下......我已经多次遇到过这个问题,但似乎没有解决这个问题......我知道修复但是我想知道如何以及为什么 (2认同)