如何写出高效的sql的一点想法及oracle常用hint用法

2023-11-18

author:skate

time:2009-05-15


 

如何写出高效的sql的一点想法

 

迷糊的问题:

 

1.什么样的sql,才算是高效的sql呢?
2.sql为什么不走索引?如何让sql走索引,即改变sql的执行计划
3.索引有哪几种?
4,什时候用索引,什么时候全表扫描

 

oracle优化器的表统计信息,评估出表的最佳连接顺序,表的连接方法,执行路径;
最后生成执行计划,oracle就按着这个计划来执行sql

 

1.什么样的sql是高效sql?


答:最本质答案就是执行时间最短,怎么才能最短了,就是用最少的资源把事办了,不做无用功;
    即使sql的io最少,那怎么样才才能最少呢?就是尽量用索引,不要全表扫描;在多表关联的
    时候,开发人选正确的表连接方法,执行路径等

 

2.sql为何不走索引

 

A.类型不匹配
B。条件列包含函数但没有创建相应的函数索引
C。复合索引中的前导列没有被做为查询条件
D。CBO的模式下,选择的行数比例较大,优化器选择全表扫描
E。CBO的模式下,表很久没有分析,优化器选择了全表扫描


3.索引种类及创建方法

 

A。B*索引

 

create index indexname on tablename(columnname);

 

B.反向索引

 

create index indexname on tablename(columnname) reverse;

 

C.降序索引

 

create index indexname on tablename(columnname desc);

 

D.位图索引

 

create bitmap index indexname on tablename(columnname);

 

E。函数索引

 

create index indexname on tablename(functionname(columnname));


4,什时候用索引,什么时候用全表扫描?

 

答:

 

要使用索引时,首先要弄清一些基本信息
表有多少行?查询返回多少行?表的哪些列上有索引?都是什么样的索引?
在有多个条件列时,应该选择什么样的索引?

 

A.当查询的记录数,在有序表中小于40%的时候,最好用索引;否则用全表扫描
B.当查询的记录数,在有无序表中小于7%的时候,最好用索引;否则用全表扫描
C.表的锁片较多时(这个表dml操作很频繁)

 

oracle常用hint的用法

 

写HINT目的


手工指定SQL语句的执行计划
hints是oracle提供的一种机制,用来告诉优化器按照我们的告诉它的方式生成执行计划。我们可以用hints来实现:
1) 使用的优化器的类型
2) 基于代价的优化器的优化目标,是all_rows还是first_rows。
3) 表的访问路径,是全表扫描,还是索引扫描,还是直接利用rowid。
4) 表之间的连接类型
5) 表之间的连接顺序
6) 语句的并行程度

 

2、HINT可以基于以下规则产生作用


表连接的顺序、表连接的方法、访问路径、并行度

 

3、HINT应用范围


dml语句
查询语句

 

4、语法
{DELETE|INSERT|SELECT|UPDATE} /*+ hint [text] [hint[text]]... */
or
{DELETE|INSERT|SELECT|UPDATE} --+ hint [text] [hint[text]]...
如果语(句)法不对,则ORACLE会自动忽略所写的HINT,不报错

 

1. /*+ALL_ROWS*/
表明对语句块选择基于开销的优化方法,并获得最佳吞吐量,使资源消耗最小化.
例如:
SELECT /*+ALL_ROWS*/ EMP_NO,EMP_NAM,DAT_IN FROM BSEMPMS WHERE EMP_NO='SCOTT';


2. /*+FIRST_ROWS*/
表明对语句块选择基于开销的优化方法,并获得最佳响应时间,使资源消耗最小化.
例如:
SELECT /*+FIRST_ROWS*/ EMP_NO,EMP_NAM,DAT_IN FROM BSEMPMS WHERE EMP_NO='SCOTT';


3. /*+CHOOSE*/
表明如果数据字典中有访问表的统计信息,将基于开销的优化方法,并获得最佳的吞吐量;
表明如果数据字典中没有访问表的统计信息,将基于规则开销的优化方法;
例如:
SELECT /*+CHOOSE*/ EMP_NO,EMP_NAM,DAT_IN FROM BSEMPMS WHERE EMP_NO='SCOTT';

 

4. /*+RULE*/
表明对语句块选择基于规则的优化方法.
例如:
SELECT /*+ RULE */ EMP_NO,EMP_NAM,DAT_IN FROM BSEMPMS WHERE EMP_NO='SCOTT';

 

5. /*+FULL(TABLE)*/
表明对表选择全局扫描的方法.
例如:
SELECT /*+FULL(A)*/ EMP_NO,EMP_NAM FROM BSEMPMS A WHERE EMP_NO='SCOTT';

 

6. /*+ROWID(TABLE)*/
提示明确表明对指定表根据ROWID进行访问.
例如:
SELECT /*+ROWID(BSEMPMS)*/ * FROM BSEMPMS WHERE ROWID>='AAAAAAAAAAAAAA'
AND EMP_NO='SCOTT';

 

7. /*+CLUSTER(TABLE)*/
提示明确表明对指定表选择簇扫描的访问方法,它只对簇对象有效.
例如:
SELECT /*+CLUSTER */ BSEMPMS.EMP_NO,DPT_NO FROM BSEMPMS,BSDPTMS
WHERE DPT_NO='TEC304' AND BSEMPMS.DPT_NO=BSDPTMS.DPT_NO;

 

8. /*+INDEX(TABLE INDEX_NAME)*/
表明对表选择索引的扫描方法.
例如:
SELECT /*+INDEX(BSEMPMS SEX_INDEX) USE SEX_INDEX BECAUSE THERE ARE FEWMALE BSEMPMS */ FROM BSEMPMS WHERE SEX='M';

 

9. /*+INDEX_ASC(TABLE INDEX_NAME)*/
表明对表选择索引升序的扫描方法.
例如:
SELECT /*+INDEX_ASC(BSEMPMS PK_BSEMPMS) */ FROM BSEMPMS WHERE DPT_NO='SCOTT';

 

10. /*+INDEX_COMBINE*/
为指定表选择位图访问路经,如果INDEX_COMBINE中没有提供作为参数的索引,将选择出位图索引的布尔组合方式.
例如:
SELECT /*+INDEX_COMBINE(BSEMPMS SAL_BMI HIREDATE_BMI)*/ * FROM BSEMPMS
WHERE SAL<5000000 AND HIREDATE

 

11. /*+INDEX_JOIN(TABLE INDEX_NAME)*/
提示明确命令优化器使用索引作为访问路径.
例如:
SELECT /*+INDEX_JOIN(BSEMPMS SAL_HMI HIREDATE_BMI)*/ SAL,HIREDATE
FROM BSEMPMS WHERE SAL<60000;

 

12. /*+INDEX_DESC(TABLE INDEX_NAME)*/
表明对表选择索引降序的扫描方法.
例如:
SELECT /*+INDEX_DESC(BSEMPMS PK_BSEMPMS) */ FROM BSEMPMS WHERE DPT_NO='SCOTT';

13. /*+INDEX_FFS(TABLE INDEX_NAME)*/


对指定的表执行快速全索引扫描,而不是全表扫描的办法.
例如:
SELECT /*+INDEX_FFS(BSEMPMS IN_EMPNAM)*/ * FROM BSEMPMS WHERE DPT_NO='TEC305';

 

14. /*+ADD_EQUAL TABLE INDEX_NAM1,INDEX_NAM2,...*/
提示明确进行执行规划的选择,将几个单列索引的扫描合起来.
例如:
SELECT /*+INDEX_FFS(BSEMPMS IN_DPTNO,IN_EMPNO,IN_SEX)*/ * FROM BSEMPMS WHERE EMP_NO='SCOTT' AND DPT_NO='TDC306';

 

15. /*+USE_CONCAT*/
对查询中的WHERE后面的OR条件进行转换为UNION ALL的组合查询.
例如:
SELECT /*+USE_CONCAT*/ * FROM BSEMPMS WHERE DPT_NO='TDC506' AND SEX='M';

 

16. /*+NO_EXPAND*/
对于WHERE后面的OR 或者IN-LIST的查询语句,NO_EXPAND将阻止其基于优化器对其进行扩展.
例如:
SELECT /*+NO_EXPAND*/ * FROM BSEMPMS WHERE DPT_NO='TDC506' AND SEX='M';

 

17. /*+NOWRITE*/
禁止对查询块的查询重写操作.

 

18. /*+REWRITE*/
可以将视图作为参数.

 

19. /*+MERGE(TABLE)*/
能够对视图的各个查询进行相应的合并.
例如:
SELECT /*+MERGE(V) */ A.EMP_NO,A.EMP_NAM,B.DPT_NO FROM BSEMPMS A (SELET DPT_NO
,AVG(SAL) AS AVG_SAL FROM BSEMPMS B GROUP BY DPT_NO) V WHERE A.DPT_NO=V.DPT_NO
AND A.SAL>V.AVG_SAL;

 

20. /*+NO_MERGE(TABLE)*/
对于有可合并的视图不再合并.
例如:
SELECT /*+NO_MERGE(V) */ A.EMP_NO,A.EMP_NAM,B.DPT_NO FROM BSEMPMS A (SELECT DPT_NO,AVG(SAL) AS AVG_SAL FROM BSEMPMS B GROUP BY DPT_NO) V WHERE A.DPT_NO=V.DPT_NO AND A.SAL>V.AVG_SAL;

 

21. /*+ORDERED*/
根据表出现在FROM中的顺序,ORDERED使ORACLE依此顺序对其连接.
例如:
SELECT /*+ORDERED*/ A.COL1,B.COL2,C.COL3 FROM TABLE1 A,TABLE2 B,TABLE3 C WHERE A.COL1=B.COL1 AND B.COL1=C.COL1;

 

22. /*+USE_NL(TABLE)*/
将指定表与嵌套的连接的行源进行连接,并把指定表作为内部表.
例如:
SELECT /*+ORDERED USE_NL(BSEMPMS)*/ BSDPTMS.DPT_NO,BSEMPMS.EMP_NO,BSEMPMS.EMP_NAM FROM BSEMPMS,BSDPTMS WHERE BSEMPMS.DPT_NO=BSDPTMS.DPT_NO;

 

23. /*+USE_MERGE(TABLE)*/
将指定的表与其他行源通过合并排序连接方式连接起来.
例如:
SELECT /*+USE_MERGE(BSEMPMS,BSDPTMS)*/ * FROM BSEMPMS,BSDPTMS WHERE BSEMPMS.DPT_NO=BSDPTMS.DPT_NO;

 

24. /*+USE_HASH(TABLE)*/
将指定的表与其他行源通过哈希连接方式连接起来.
例如:
SELECT /*+USE_HASH(BSEMPMS,BSDPTMS)*/ * FROM BSEMPMS,BSDPTMS WHERE BSEMPMS.DPT_NO=BSDPTMS.DPT_NO;

 

25. /*+DRIVING_SITE(TABLE)*/
强制与ORACLE所选择的位置不同的表进行查询执行.
例如:
SELECT /*+DRIVING_SITE(DEPT)*/ * FROM BSEMPMS,DEPT@BSDPTMS WHERE BSEMPMS.DPT_NO=DEPT.DPT_NO;

 

26. /*+LEADING(TABLE)*/
将指定的表作为连接次序中的首表.

 

27. /*+CACHE(TABLE)*/
当进行全表扫描时,CACHE提示能够将表的检索块放置在缓冲区缓存中最近最少列表LRU的最近使用端
例如:
SELECT /*+FULL(BSEMPMS) CAHE(BSEMPMS) */ EMP_NAM FROM BSEMPMS;

 

28. /*+NOCACHE(TABLE)*/
当进行全表扫描时,CACHE提示能够将表的检索块放置在缓冲区缓存中最近最少列表LRU的最近使用端
例如:
SELECT /*+FULL(BSEMPMS) NOCAHE(BSEMPMS) */ EMP_NAM FROM BSEMPMS;

 

29. /*+APPEND*/
直接插入到表的最后,可以提高速度.
insert /*+append*/ into test1 select * from test4 ;

 

30. /*+NOAPPEND*/
通过在插入语句生存期内停止并行模式来启动常规插入.
insert /*+noappend*/ into test1 select * from test4 ;

 

31.  NO_INDEX: 指定不使用哪些索引
/*+ NO_INDEX ( table [index [index]...] ) */
select /*+ no_index(emp ind_emp_sal ind_emp_deptno)*/ * from emp where deptno=200 and sal>300;


32.  parallel

select /*+ parallel(emp,4)*/ * from emp where deptno=200 and sal>300;


另:每个SELECT/INSERT/UPDATE/DELETE命令后只能有一个/*+ */,但提示内容可以有多个,可以用逗号分开,空格也可以。如:
/*+ ordered index() use_nl() */

 

 

---end---

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何写出高效的sql的一点想法及oracle常用hint用法 的相关文章

随机推荐

  • 【Python基础】Jupyter Notebook最常用的五大配置技巧

    说到Jupyter Notebook 以下简称Jupyter 想必很多人都不陌生 这是一款神奇的web应用 权且可以把它当作python超级笔记本 当然它还支持R Julia Scala Js等几十种语言 在Jupyter上 可以使用pyt
  • Spring Security OAuth2.0(四)-----OAuth2+JWT

    传统的通过 session 来记录用户认证信息的方式我们可以理解为这是一种有状态登录 而 JWT 则代表了一种无状态登录 无状态登录天然的具备单点登录能力 1 无状态登录 1 1 什么是有状态 有状态服务 即服务端需要记录每次会话的客户端信
  • Python中__str__的用法

    str 和 repr 如果要把一个类的实例变成 str 就需要实现特殊方法 str 不使用 str print打印出来是个对象 使用了就把对象变成字符串 class Person object def init self name gend
  • 蓝桥杯模块练习6-AD

    main c include
  • ag-grid Column API(机器翻译)

    Column API 一些API方法采用colKey类型为的列关键字 名为 Column string 这意味着您可以传递一个Column对象 通过调用其他方法之一接收到的对象 也可以传递Column ID 即string 列ID是列定义的
  • 【毕业设计】深度学习卫星遥感图像检测与识别系统(目标检测)

    文章目录 0 前言 1 课题背景 2 实现效果 3 Yolov5算法 4 数据处理和训练 5 最后 0 前言 Hi 大家好 这里是丹成学长的毕设系列文章 对毕设有任何疑问都可以问学长哦 这两年开始 各个学校对毕设的要求越来越高 难度也越来越
  • 远程控制,从个人便捷走向企业安全

    根据风险基础安全 Risk Based Security 的数据显示 2020年全球数据泄漏达到360亿条 创历史新高 对比传统的网络安全威胁 数据安全威胁更加多样化 80 的安全风险来自于内部人员或合作伙伴 威胁形式也更集中在账号体系薄弱
  • mybatis中association和collection的column传入多个参数问题

    mybatis中association和collection的column传入多个参数值 项目中在使用association和collection实现一对一和一对多关系时需要对关系中结果集进行筛选 如果使用懒加载模式 即联合使用select
  • mysql mariadb不能启动原因_centOS7 (64) MariaDB无法启动 跪求解决方法

    在CentOS7中mysql被 MariaDB所代替 幸得 贵在坚持 提点 顺利下载 MariaDB等相关软件但是安装完毕后 mariadb还是无法正常启动 root localhost service mariadb start Redi
  • mysql怎么替换部分字符串

    mysql替换部分字符串的方法 1 使用REPLACE 函数 语法 REPLACE 字符串 查找值 替换值 2 使用INSERT 函数 语法 INSERT 字符串 替换开始位置 要替换的字符数 替换值 mysql替换部分字符串 1 使用RE
  • 多租户mysql架构_团队开发框架实战—多租户架构

    1 对多租户的理解 多租户定义 多租户技术或称多重租赁技术 简称SaaS 是一种软件架构技术 是实现如何在多用户环境下 此处的多用户一般是面向企业用户 共用相同的系统或程序组件 并且可确保各用户间数据的隔离性 简单讲 在一台服务器上运行单个
  • XSS 跨站脚本

    XSS 跨站脚本 一 什么是XSS XSS Cross site Scripting 中文名跨站脚本攻击 其原理是攻击者利用浏览器执行前端代码 HTML CSS JavaScript 的特性 将恶意的JavaScript代码插入到页面中 当
  • LVGL动态图GIF实现 v7 version

    lvglv8 1以上的版本自带动态图库 github网址 LVGL GitHub 主要包含四个文件 gifdec c gifdec h lv gif c lvgif h 目录 lvgl release v8 1 lvgl release v
  • Cortex-AX系列性能对比

    首先要明确一个概念 Cortex并不是一种架构 而是ARM的一个系列 Cortex A系列 而我们通常意义的ARM7 ARM9 ARM11才是所谓的架构 同时需注意 Cortex A5 Cortex A8 Cortex A9 Cortex
  • ELF文件格式

    在介绍ELF格式之前 先简单说明一下可执行文件的生成流程 1 编写C源文件 或汇编源文件 2 准备共享库格式的目标文件 shared object file 如数学库 标准库 2 用编译器 compiler 将C编译成可重定位格式的目标文件
  • 关于pickle的load,loads等

    基础知识 python自带的file函数只能存储和读取字符串格式的数据 pickle可以存储和读取成其他格式比如list dict的数据 来自 https www zhihu com question 38355589 如需更详细 关于lo
  • 三十八、java版 SpringCloud分布式微服务云架构之Java 网络编程

    Java 网络编程 网络编程是指编写运行在多个设备 计算机 的程序 这些设备都通过网络连接起来 java net 包中 J2SE 的 API 包含有类和接口 它们提供低层次的通信细节 你可以直接使用这些类和接口 来专注于解决问题 而不用关注
  • windows定时自动备份

    windows定时自动备份 1 创建bat脚本 1 本地备份 复制以下代码保存该文件 修改文件名为以 bat结尾的文件 echo off echo 正在复制 C a 文件夹的内容至 D b 文件夹下 xcopy C a D b e I d
  • pip 命令行“ImportError: No Module Named Typing”

    pip遇到ImportError No Module Named Typing 原因在于运行的是python2版本 升级到python3就不会有这个问题 但是因为Mac中同时有python2和python3 可以把pip安装在python3
  • 如何写出高效的sql的一点想法及oracle常用hint用法

    author skate time 2009 05 15 如何写出高效的sql的一点想法 迷糊的问题 1 什么样的sql 才算是高效的sql呢 2 sql为什么不走索引 如何让sql走索引 即改变sql的执行计划3 索引有哪几种 4 什时候