Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1423957
  • 博文数量: 176
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 3871
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-30 13:00
个人简介

About me:Oracle ACE pro,optimistic,passionate and harmonious. Focus on ORACLE,MySQL and other database programming,peformance tuning,db design, j2ee,Linux/AIX,Architecture tech,etc

文章分类

全部博文(176)

文章存档

2025年(4)

2024年(27)

2023年(28)

2022年(43)

2020年(62)

2014年(3)

2013年(9)

分类: Oracle

2025-02-20 08:40:55

having普通列(非聚合条件)提升到where里,在分组之前过滤,如果having的普通列可以走索引效率好,这种提升有好处
测试下来,只有pg支持,MySQL文档说支持,但是测试部支持,oracle不支持
能放到where里的条件不要放到having里,是编写SQL的准则之一


---MySQL
文档8.2.1.1 WHERE Clause Optimization
HAVING is merged with WHERE if you do not use GROUP BY or aggregate functions (COUNT(), MIN(), and so on).


这里说having在没有group by或聚合函数情况下,可以转到where里,测试也不行


##mysql支持查找非分组列,支持无分组的having 列条件,pg和oracle不支持这种,id有索引但是没有走

点击(此处)折叠或打开

  1. explain analyze select * from sub_t having id<10\G
  2. *************************** 1. row ***************************
  3. EXPLAIN: -> Filter: (sub_t.id < 10) (cost=10059.85 rows=99876) (actual time=0.837..64.590 rows=900 loops=1)
  4.     -> Table scan on sub_t (cost=10059.85 rows=99876) (actual time=0.032..59.453 rows=99990 loops=1)

  5. 1 row in set (0.06 sec)

## 改成where走索引

点击(此处)折叠或打开

  1. explain analyze select * from sub_t where id<10\G
  2. *************************** 1. row ***************************
  3. EXPLAIN: -> Index range scan on sub_t using idx1_sub_t over (id < 10), with index condition: (sub_t.id < 10) (cost=405.26 rows=900) (actual time=0.032..2.085 rows=900 loops=1)

  4. explain analyze select id,max(name) from sub_t group by id having id<10\G
  5. *************************** 1. row ***************************
  6. EXPLAIN: -> Filter: (sub_t.id < 10) (cost=20047.45 rows=99876) (actual time=0.323..215.649 rows=9 loops=1)
  7.     -> Group aggregate: max(sub_t.`name`) (cost=20047.45 rows=99876) (actual time=0.322..215.389 rows=1000 loops=1)
  8.         -> Index scan on sub_t using idx1_sub_t (cost=10059.85 rows=99876) (actual time=0.038..181.364 rows=99990 loops=1)

  9. 1 row in set (0.21 sec)
----pg
不支持这种语法

点击(此处)折叠或打开

  1. explain analyze select * from sub_t having id<10;
  2. ERROR: syntax error at or near "explain"
  3. LINE 2: explain analyze select * from sub_t having id<10;
  4.         ^

pg支持having是普通列条件,直接提升到where里在分组计算之前过滤,这样可以走索引


点击(此处)折叠或打开

  1. explain analyze select id,max(name) from sub_t group by id having id<10;
  2.                                                        QUERY PLAN
  3. -------------------------------------------------------------------------------------------------------------------------
  4.  GroupAggregate (cost=0.29..8.62 rows=10 width=36) (actual time=0.017..0.023 rows=9 loops=1)
  5.    Group Key: id
  6.    -> Index Scan using idx1_sub_t on sub_t (cost=0.29..8.47 rows=10 width=7) (actual time=0.008..0.011 rows=9 loops=1)
  7.          Index Cond: (id < 10)
  8.  Planning Time: 0.158 ms
  9.  Execution Time: 0.052 ms


oracle和mysql一样,也不支持having条件提升到where里 

点击(此处)折叠或打开

  1. select id,max(name) from sub_t group by id having id<10;

  2. no rows selected

  3. Elapsed: 00:00:00.07

  4. Execution Plan
  5. ----------------------------------------------------------
  6. Plan hash value: 1839928944

  7. -----------------------------------------------------------------------------
  8. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
  9. -----------------------------------------------------------------------------
  10. | 0 | SELECT STATEMENT | | 2 | 24 | 76 (11)| 00:00:01 |
  11. |* 1 | FILTER | | | | | |
  12. | 2 | HASH GROUP BY | | 2 | 24 | 76 (11)| 00:00:01 |
  13. | 3 | TABLE ACCESS FULL| SUB_T | 99991 | 1171K| 69 (2)| 00:00:01 |
  14. -----------------------------------------------------------------------------

  15. Predicate Information (identified by operation id):
  16. ---------------------------------------------------

  17.    1 - filter("ID"<10)


  18. Statistics
  19. ----------------------------------------------------------
  20.          79 recursive calls
  21.           0 db block gets
  22.         316 consistent gets
  23.         239 physical reads
  24.           0 redo size
  25.         425 bytes sent via SQL*Net to client
  26.         406 bytes received via SQL*Net from client
  27.           1 SQL*Net roundtrips to/from client
  28.           6 sorts (memory)
  29.           0 sorts (disk)
  30.           0 rows processed

  31. select id,max(name) from sub_t where id<10 group by id;

  32. no rows selected

  33. Elapsed: 00:00:00.01

  34. Execution Plan
  35. ----------------------------------------------------------
  36. Plan hash value: 1344960120

  37. ------------------------------------------------------------------------------------------
  38. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
  39. ------------------------------------------------------------------------------------------
  40. | 0 | SELECT STATEMENT | | 1 | 12 | 3 (0)| 00:00:01 |
  41. | 1 | SORT GROUP BY NOSORT | | 1 | 12 | 3 (0)| 00:00:01 |
  42. | 2 | TABLE ACCESS BY INDEX ROWID| SUB_T | 1 | 12 | 3 (0)| 00:00:01 |
  43. |* 3 | INDEX RANGE SCAN | IDX_SUB_T | 1 | | 2 (0)| 00:00:01 |
  44. ------------------------------------------------------------------------------------------

  45. Predicate Information (identified by operation id):
  46. ---------------------------------------------------

  47.    3 - access("ID"<10)


  48. Statistics
  49. ----------------------------------------------------------
  50.           1 recursive calls
  51.           0 db block gets
  52.           2 consistent gets
  53.           5 physical reads
  54.           0 redo size
  55.         425 bytes sent via SQL*Net to client
  56.         410 bytes received via SQL*Net from client
  57.           1 SQL*Net roundtrips to/from client
  58.           0 sorts (memory)
  59.           0 sorts (disk)
  60.           0 rows processed


阅读(33) | 评论(0) | 转发(0) |
0

上一篇:MySQL的RR模式解决不可重复读和幻读了吗?

下一篇:没有了

给主人留下些什么吧!~~