外贸有限公司英文网站,沈阳室内设计公司排名,开封网站推广,龙之网官网#x1f4ab;《博主介绍》#xff1a;✨又是一天没白过#xff0c;我是奈斯#xff0c;从事IT领域✨ #x1f4ab;《擅长领域》#xff1a;✌️擅长阿里云AnalyticDB for MySQL(分布式数据仓库)、Oracle、MySQL、Linux、prometheus监控#xff1b;并对SQLserver、NoSQL(… 《博主介绍》✨又是一天没白过我是奈斯从事IT领域✨ 《擅长领域》✌️擅长阿里云AnalyticDB for MySQL(分布式数据仓库)、Oracle、MySQL、Linux、prometheus监控并对SQLserver、NoSQL(MongoDB)有了解✌️ 大佬们都喜欢静静的看文章并且也会默默的点赞收藏加关注 今天这篇文章分享一下《使用Hint对优化器的执行计划进行干预》。首先需要明白为什么需要人工干预SQL语句的执行计划不是Oracle的优化器会根据统计信息对每个SQL语句执行最优的执行计划的吗干哈还需要人工来指定执行计划呢那么我先给出答案 在大多数情况优化器是会给出最优的执行计划但并不是所有的情况 。 比如现在有这么一个场景假设有两张业务表 orders 和 customers 并且它们通过 customer_id 列关联。我们需要查询所有来自特定城市例如“New York”的客户订单数据。Oracle优化器通常会根据统计信息来选择最优的执行计划可能会选择通过 orders 表进行全表扫描甚至可能选择一个不那么高效的连接顺序。此时我们可以使用 LEADING Hint 来干预优化器让它首先选择 customers 表然后再进行连接操作通过指定 /* LEADING(customers) */ 告诉优化器优先选择 customers 表来作为驱动表而不是默认可能的 orders 表。这样做的好处是当 customers 表的数据量较小而 orders 表的数据量较大时优化器通过首先选择小表 customers 来驱动连接让查询按照我们期望的顺序执行可以避免在大表上做不必要的扫描从而提高查询效率。这只是众多需要hint干预的一种情况还有很多其他情况那么带着这些问题开始今天的内容。 特别说明本篇文章部分知识点均来源于 Oracle 公开可查的官方文档手册并结合了我个人的理解和案例演示。如有冲突请联系会立即处理。转载请标明出处 官方文档对Hint的详细介绍Oracle 12cInfluencing the Optimizer 目录
一、使用Hint对优化器的执行计划进行干预
Hint的优点
Hint的缺点
Hint的范围
Hint写法
联接顺序Hint准则
1、Hint干预的类型
1.1 单表单表Hint是在一个表或视图上指定
1.1.1 FULL Hint
1.1.2 INDEX Hint
1.1.3 INDEX_ASC Hint
1.1.4 INDEX_DESC Hint
1.1.5 INDEX_FFS Hint
1.1.6 INDEX_JOIN Hint
1.1.7 INDEX_SS Hint
1.1.8 INDEX_SS_ASC Hint
1.1.9 INDEX_SS_DESC Hint
1.2 多表多表Hint类似于单表Hint只是该Hint可以指定多个表或视图
1.2.1 LEADING Hint
1.2.2 MERGE Hint
1.2.3 USE_BAND Hint
1.2.4 USE_CONCAT Hint
1.2.5 USE_CUBE Hint
1.2.6 USE_HASH Hint
1.2.7 USE_MERGE Hint
1.2.8 USE_NL Hint
1.2.9 USE_NL_WITH_INDEX Hint
1.3 查询块查询块Hint对单个查询块进行操作
1.3.1 STAR_TRANSFORMATION Hint
1.3.2 UNNEST Hint
1.4 声明声明Hint适用于整个SQL语句
1.4.1 ALL_ROWS Hint
1.4.2 FIRST_ROWS Hint 干预优化器执行计划的几种技术方式 Oracle提供了多种干预执行计划的技术包括DBMS_STATS、SQL profiles、SQL Plan Management、参数优化器相关和最后的hint方式。下图是博主手绘了一张关于干预优化器执行计划的五种方式 技术描述参数优化器相关参数在数据库实例和会话级别影响许多类型的优化器行为。Hints Hint是SQL语句中的特殊注释它将指令传递给优化器。Hint 的主要作用是向优化器提供指示按照用户预先定义的计划来执行 SQL 语句的执行计划。 DBMS_STATS 官方文档中将DBMS_STATS包定义为了干预优化器执行计划的技术。但是严格意义上来说DBMS_STATS只是用来收集统计信息的包统计信息越精准优化器选择的执行计划就越优但并不能通过DBMS_STATS包指定想要的执行计划因为DBMS_STATS收集完成统计信息之后优化器会根据统计信息对每个SQL语句执行最优的执行计划这个过程是Oracle优化器完成的人工并没有参与。 SQL profiles Oracle绑定执行计划有两种方式SQL Profile和SQL Plan Management (SPM)。其中对于Oracle 10g 及之前的版本一般采用SQL Profile来绑定执行计划而对于Oracle 11g以后的版本一般采用SPM来实现自动化的执行计划管理。 SQL plan management 干预优化器执行计划的五种技术方式今天只介绍Hints方式。 关于参数优化器相关这种方式因为在大多数情况下参数都是最优的所以一般不需要进行调整关于SQL profiles、SQL plan management和DBMS_STATS这三种方式因为文章篇幅的原因这篇文章就不做介绍了哦因为这三种方式涉及到的内容非常多需要专门写对应的博客 需要干预优化器执行计划的几种情况 在Oracle数据库中基于代价的优化器Cost-Based OptimizerCBO通常能够自动选择最优的执行计划来执行SQL语句。然而在某些特定情况下优化器可能无法选择出最优的执行计划在大多数情况优化器是会给出最优的执行计划但并不是所有的情况这时就需要干预优化器的执行计划。以下是需要进行干预的几种典型情况 优化器选择不当的执行计划有时优化器可能因为统计信息不准确、物理结构不合理如缺少合适的索引或数据分布的变化等原因选择了不理想的执行计划导致SQL语句执行效率低下。此时DBA可以通过hint来指定存取路径或连接类型引导优化器生成更优的执行计划。特定场景下的优化需求在某些特定场景下如需要快速返回查询结果的前几行而不是全部结果或者当全表扫描比索引扫描更有效时DBA可以通过hint来指定优化器的优化目标或访问路径以满足特定的业务需求。数据结构和数据规模发生重大变化当数据结构或数据规模发生重大变化时原有的执行计划可能不再适用。此时DBA可以通过hint来指示优化器使用新的存取路径或连接类型以适应变化后的数据环境。避免复杂的提示和保持执行计划稳定性在某些情况下仅通过转换优化器的模式就可以获得非常好的执行计划此时无需额外使用复杂的hint。然而在某些复杂查询中为了确保优化器产生最优的执行计划可能需要指定全套的hint包括存取路径、连接类型、连接顺序等。同时为了避免执行计划的不稳定DBA也需要在必要时使用hint来固定执行计划。应对特殊表或索引的访问需求对于某些特殊的表或索引如聚簇索引或分区表DBA可能需要通过hint来指示优化器按照特定的方式访问数据以提高查询性能。 需要注意的是Hint 是用来约束优化器行为的一种技术用来辅助DBA和研发人员用来做性能排查和优化过多的干预可能会导致执行计划不稳定甚至恶化查询性能因此尽量避免在开发中使用。毕竟数据是不断变化的大多数情况下应该让Oracle自行决定采用什么样的执行计划。 一、使用Hint对优化器的执行计划进行干预 使用Hint来影响优化器模式optimizer mode、查询转换query transformation、访问路径access path、连接顺序join order和连接方法join methods。 当发现一条 SQL 执行效率较低即执行时间较长时首先需要查看该 SQL 的执行计划。如果分析后发现执行计划不够优化就需要调查 CBO 为什么选择了不合适的执行计划。通过使用 hint 来修改执行计划并比较两种执行计划的效率从而确定最优方案。此外若 CBO 选择了错误的执行计划还应检查表的统计信息是否最新是否对相关列创建了直方图是否对分区表进行了全局或分区级别的统计分析等。 总结Hint 的主要作用是向优化器提供指示按照用户预先定义的计划来执行 SQL 语句的执行计划。 Hint的优点 在测试环境中Hint对于测试特定访问路径的性能非常有用。例如小伙伴们可能知道走索引对某些查询更具选择性在这种情况下使用Hint会让优化器生成更好的执行计划如下图所示 Hint的缺点 Oracle 7中引入了Hint由于Hint是人工定义的计划所以这部分是额外的部分也就是每次执行SQL时都要写上就比较麻烦Oracle官网给的好办法就是使用Hint进行测试如果使用Hint的执行计划提高了SQL效率然后通过使用其他技术来管理执行计划。Oracle提供了几个SQL优化工具用于替代Hint并且Oracle官网强烈建议使用这些工具而不是Hint包括SQL调优顾问SQL Tuning Advisor、SQL计划管理SQL plan management和SQL性能分析器SQL Performance Analyzer以解决优化器无法解决的性能问题。 Hint的范围 在语句块中指定Hint时该Hint将应用于相应的查询块、表或语句块中的整个语句。Hint会覆盖任何实例级或会话级参数。 Hint支持的语句有 1. MERGE、SELECT、INSERT、UPDATE、DELETE语句中 2. 父语句或者子查询中 3. 集合查询中UNION、MINUS、INTERSECT Hint写法 Hint注释必须紧跟在SQL语句块的第一个关键字之后。可以使用两种注释样式斜线星号/*或一对破折号--。加号提示分隔符必须紧跟在注释分隔符之后如以下片段所示 SELECT /* hint_text */ ... 一个语句中只能有一个包含Hint的注释但它可以包含许多空格分隔的Hint。例如一个复杂的查询可能包括多个表连接。如果只为指定的表指定INDEX提示则优化器必须确定剩余的访问路径和相应的连接方法。优化器可能不会使用INDEX提示因为连接方法和访问路径会阻止它。下图使用多个Hint来指定确切的连接顺序。 SELECT /* LEADING(e2 e1) USE_NL(e1) INDEX(e1 emp_emp_id_pk) USE_MERGE(j) FULL(j) */e1.first_name, e1.last_name, j.job_id, sum(e2.salary) total_sal
FROM employees e1, employees e2, job_history j
WHERE e1.employee_id e2.manager_id
AND e1.employee_id j.employee_id
AND e1.hire_date j.start_date
GROUP BY e1.first_name, e1.last_name, j.job_id
ORDER BY total_sal; 小提示如果Hint的写法有问题Oracle也不会提示错误哦这点真鸡肋。。。Oracle会直接忽略掉写法有问题的Hint。 联接顺序Hint准则 在某些情况下可以在SQL语句中指定联接顺序提示这样它就不会访问对结果没有影响的行。 联接中的驱动表是与其他表联接的表。一般来说驱动表包含过滤条件该条件消除了表中最高百分比的行。连接顺序对SQL语句的性能有很大的影响。 考虑以下准则 当索引更有效地检索请求的行时避免全表扫描。当可以使用获取少量行的不同索引时请避免使用从驱动表中获取许多行的索引。选择联接顺序以便在联接顺序的后面将较少的行联接到表中。 以下示例显示了如何有效地调整连接顺序 SELECT *
FROM taba a, tabb b, tabc c
WHERE a.acol BETWEEN 100 AND 200
AND b.bcol BETWEEN 10000 AND 20000
AND c.ccol BETWEEN 10000 AND 20000
AND a.key1 b.key1
AND a.key2 c.key2; 选择驱动表和驱动索引(如果有)上例中的前三个条件都是应用于单个表的筛选条件。最后两个条件是连接条件。筛选条件决定了驱动表和索引的选择。一般来说驱动表包含过滤条件可消除最高百分比的行。因为100到200的范围相对于acol的范围来说比较窄但是10000和20000的范围比较大taba就是驾驶台其他都一样。对于嵌套循环连接连接通过连接索引进行连接索引是主键或外键上的索引用于将该表连接到连接树中较早的表。除了驱动表很少在非连接条件下使用索引。因此在选择taba作为驱动表之后使用b.key1和c.key2上的索引分别驱动到tabb和tabc中。选择最佳连接顺序最早使用最佳未用过滤器通过首先连接到具有最好的仍未使用的过滤器的表可以减少后续连接的工作量。因此如果bcol BETWEEN比ccol BETWEEN更严格(拒绝更高百分比的行),那么如果在tabc之前联接tabb最后的联接会变得更容易(具有更少的行)。可以使用ORDERED或STAR提示来强制联接顺序。 1、Hint干预的类型 Hint可以对四种类型进行干预分别可以对单表Single-table、多表Multitable、查询块query blocks、声明statements使用Hint。并且Oracle提供了快100个Hint干预这篇文章也不可能介绍所有只是把我认为重要的Hint给介绍其他需要学习的可以参考官网文档哦敬上 Hint 官网链接Comments 1.1 单表单表Hint是在一个表或视图上指定
1.1.1 FULL Hint 使用语法 /* FULL ( [ queryblock ] tablespec ) */ 介绍 FULL Hint提示优化器对指定表执行全表扫描。例如 SELECT /* FULL(e) */ employee_id, last_nameFROM hr.employees e WHERE last_name LIKE :b1;数据库对employees表执行全表扫描以执行此语句即使WHERE子句中的条件使last_name列上有索引。 employees表在FROM子句中有别名e因此Hint必须通过别名而不是引用该表。即使在FROM子句中指定了表名但也不要在Hint中指定它们。 1.1.2 INDEX Hint 使用语法 /* INDEX ( [ queryblock ] tablespec [ indexspec [ indexspec ]... ] ) */ 介绍 INDEX Hint指示优化器对指定表使用索引扫描。您可以将INDEX提示用于基于函数的索引、域索引、B树索引、位图索引和位图连接索引。 如果index Hint指定了一个可用的索引那么数据库将对该索引执行扫描。优化器不会考虑全表扫描或表上另一个索引的扫描。对于多个索引组合的提示Oracle建议使用INDEX_COMBINE而不是INDEX因为它是一个更通用的提示。如果INDEX提示指定了可用索引的列表则优化器会考虑列表中每个索引的扫描成本然后以最低成本执行索引扫描。如果这种访问路径的成本最低数据库还可以选择扫描此列表中的多个索引并合并结果。数据库不考虑全表扫描或对提示中未列出的索引的扫描。如果INDEX提示未指定索引则优化器会考虑对表上每个可用索引的扫描成本然后以最低成本执行索引扫描。如果这种访问路径的成本最低数据库还可以选择扫描多个索引并合并结果。优化器不考虑全表扫描。 INDEX Hint示例 SELECT /* INDEX (employees emp_department_ix)*/ employee_id, department_idFROM employees WHERE department_id 50; 1.1.3 INDEX_ASC Hint 使用语法 /* INDEX_ASC ( [ queryblock ] tablespec [ indexspec [ indexspec ]... ] ) */ 介绍 INDEX_ASC提示指示优化器对指定表使用索引扫描。如果语句使用索引范围扫描则Oracle数据库会按索引值的升序扫描索引条目。每个参数的作用与INDEX Hint中的相同。 范围扫描的默认行为是按索引值的升序扫描索引条目或按降序扫描索引条目。此提示不会更改索引的默认顺序因此仅指定index提示。但是如果默认行为发生变化您可以使用INDEX_ASC提示显式指定升序范围扫描。 1.1.4 INDEX_DESC Hint 使用语法 /* INDEX_DESC ( [ queryblock ] tablespec [ indexspec [ indexspec ]... ] ) */ 介绍 INDEX_DESC提示指示优化器对指定表使用降序索引扫描。如果语句使用索引范围扫描并且索引是升序的则Oracle会按索引值的降序扫描索引条目。在分区索引中结果在每个分区内按降序排列。对于降序索引此提示有效地取消了降序导致按升序扫描索引条目。每个参数的作用与INDEX提示中的相同。例如 SELECT /* INDEX_DESC(e emp_name_ix) */ *FROM employees e; 1.1.5 INDEX_FFS Hint 使用语法 /* INDEX_FFS ( [ queryblock ] tablespec [ indexspec [ indexspec ]... ] ) */ 介绍 INDEX_FFS Hint指示优化器执行索引快速全扫描Index Fast Full Scans而不是全表扫描。每个参数的作用与INDEX提示中的相同。例如 SELECT /* INDEX_FFS(e emp_name_ix) */ first_nameFROM employees e; 1.1.6 INDEX_JOIN Hint 使用语法 /* INDEX_JOIN ( [ queryblock ] tablespec [ indexspec [ indexspec ]... ] ) */ 介绍 INDEX_JOIN Hint指示优化器使用索引联接作为访问路径。为了使提示产生积极的效果必须存在足够少的索引其中包含解析查询所需的所有列。 每个参数的作用与INDEX Hint中的相同。例如以下查询使用索引联接来访问manager_id和department_id列这两列都在employees表中索引。 SELECT /* INDEX_JOIN(e emp_manager_ix emp_department_ix) */ department_idFROM employees eWHERE manager_id 110AND department_id 50; 1.1.7 INDEX_SS Hint 使用语法 /* INDEX_SS ( [ queryblock ] tablespec [ indexspec [ indexspec ]... ] ) */ 介绍 INDEX_SS Hint指示优化器对指定表执行索引跳跃扫描Index Skip Scans。如果语句使用索引范围扫描则Oracle会按索引值的升序扫描索引条目。在分区索引中结果在每个分区内按升序排列。 每个参数的作用与INDEX Hint中的相同。例如 SELECT /* INDEX_SS(e emp_name_ix) */ last_nameFROM employees eWHERE first_name Steven; 1.1.8 INDEX_SS_ASC Hint 使用语法 /* INDEX_SS_ASC ( [ queryblock ] tablespec [ indexspec [ indexspec ]... ] ) */ 介绍 INDEX_SS_ASC提示指示优化器对指定的表执行索引跳过扫描。如果语句使用索引范围扫描那么Oracle数据库将按照索引值的升序扫描索引条目。在分区索引中结果在每个分区中按升序排列。每个参数的作用与INDEX Hint中的相同。 范围扫描的默认行为是按照索引值的升序扫描索引项或者按照降序扫描降序索引项。该提示不会更改索引的默认顺序因此除了INDEX_SS提示之外不会指定任何其他内容。但是如果默认行为发生变化可以使用INDEX_SS_ASC提示显式指定升序范围扫描。 1.1.9 INDEX_SS_DESC Hint 使用语法 /* INDEX_SS_DESC ( [ queryblock ] tablespec [ indexspec [ indexspec ]... ] ) */ 介绍 INDEX_SS_DESC提示指示优化器对指定的表执行索引跳过扫描。如果语句使用索引范围扫描并且索引是升序的那么Oracle将按照索引值的降序扫描索引条目。在分区索引中结果在每个分区中按降序排列。对于降序索引该提示有效地取消了降序从而以升序扫描索引条目。 每个参数的作用与index Hint中的相同。例如 SELECT /* INDEX_SS_DESC(e emp_name_ix) */ last_nameFROM employees eWHERE first_name Steven; 1.2 多表多表Hint类似于单表Hint只是该Hint可以指定多个表或视图
1.2.1 LEADING Hint 使用语法 /* LEADING ( [ queryblock ] tablespec [ tablespec ]... ) */ 介绍 LEADING提示指示优化器使用指定的一组表作为执行计划中的前缀。这个提示比有序提示更通用。例如 SELECT /* LEADING(e j) */ *FROM employees e, departments d, job_history jWHERE e.department_id d.department_idAND e.hire_date j.start_date;如果指定的表由于连接图中的依赖关系而无法按指定的顺序首先连接则忽略LEADING Hint。如果指定了两个或更多冲突的LEADING Hint则所有这些提示都将被忽略。如果指定ORDERED提示它将覆盖所有LEADING Hint。 1.2.2 MERGE Hint 使用语法 /* MERGE [ ( queryblock ) | ( [ queryblock ] tablespec ) ] */ 介绍 MERGE提示允许合并查询中的视图。 如果视图的查询块在选择列表中包含GROUP BY子句或DISTINCT运算符则只有在启用了复杂视图合并时优化器才能将视图合并到访问语句中。如果子查询不相关也可以使用复杂合并将IN子查询合并到访问语句中。示例 SELECT /* MERGE(v) */ e1.last_name, e1.salary, v.avg_salaryFROM employees e1,(SELECT department_id, avg(salary) avg_salary FROM employees e2GROUP BY department_id) v WHERE e1.department_id v.department_idAND e1.salary v.avg_salaryORDER BY e1.last_name;使用不带参数的MERGE提示时应该将其放在视图查询块中。当MERGE与作为参数的视图名称一起使用时它应该放在周围的查询中。 1.2.3 USE_BAND Hint 使用语法 /* USE_BAND ( [ queryblock ] tablespec [ tablespec ]... ) */ 介绍 USE_BAND提示指示优化器使用带连接将每个指定的表与另一个行源连接起来。例如 SELECT /* USE_BAND(e1 e2) */e1.last_name|| has salary between 100 less and 100 more than || e2.last_name AS SALARY COMPARISON
FROM employees e1, employees e2
WHERE e1.salary BETWEEN e2.salary - 100 AND e2.salary 100; 1.2.4 USE_CONCAT Hint 使用语法 /* USE_CONCAT [ ( queryblock ) ] */ 介绍 USE_CONCAT提示指示优化器使用UNION ALL集合运算符将查询的WHERE子句中的组合OR条件转换为复合查询。如果没有这个提示只有当使用连接的查询成本比不使用连接的成本低时才会发生这种转换。USE_CONCAT提示覆盖了成本考虑。例如 SELECT /* USE_CONCAT */ *FROM employees eWHERE manager_id 108OR department_id 110; 1.2.5 USE_CUBE Hint 使用语法 /* USE_CUBE ( [ queryblock ] tablespec [ tablespec ]... ) */ 介绍 当联接的右侧是一个多维数据集时USE_CUBE提示指示优化器使用多维数据集联接将每个指定的表与另一个行源联接起来。如果优化器基于统计分析决定不使用多维数据集连接那么您可以使用USE_CUBE来覆盖该决定。 1.2.6 USE_HASH Hint 使用语法 /* USE_HASH ( [ queryblock ] tablespec [ tablespec ]... ) */ 介绍 USE_HASH提示指示优化器使用散列连接将每个指定的表与另一个行源连接起来。例如 SELECT /* USE_HASH(l h) */ *FROM orders h, order_items lWHERE l.order_id h.order_idAND l.order_id 2400; 1.2.7 USE_MERGE Hint 使用语法 /* USE_MERGE ( [ queryblock ] tablespec [ tablespec ]... ) */ 介绍 USE_MERGE提示指示优化器使用排序合并联接将每个指定的表与另一个行源联接起来。例如 SELECT /* USE_MERGE(employees departments) */ * FROM employees, departments WHERE employees.department_id departments.department_id;建议将USE_NL和USE_MERGE提示与LEADING和ORDERED提示一起使用。当被引用的表被强制作为连接的内部表时优化器使用这些提示。如果被引用的表是外部表则忽略提示。 1.2.8 USE_NL Hint 使用语法 /* USE_NL ( [ queryblock ] tablespec [ tablespec ]... ) */ 介绍 USE_NL提示指示优化器使用指定的表作为内部表通过嵌套循环联接将每个指定的表联接到另一个行源。 USE_NL提示指示优化器使用指定的表作为内部表通过嵌套循环联接将每个指定的表联接到另一个行源。 建议将USE_NL和USE_MERGE提示与LEADING和ORDERED提示一起使用。当被引用的表被强制作为连接的内部表时优化器使用这些提示。如果被引用的表是外部表则忽略提示。 在下面的示例中通过提示强制执行嵌套循环通过全表扫描访问orders并将筛选条件l.order_id h.order_id应用于每一行。对于满足筛选条件的每一行order_items通过索引order_id进行访问。 SELECT /* USE_NL(l h) */ h.customer_id, l.unit_price * l.quantityFROM orders h, order_items lWHERE l.order_id h.order_id;向查询中添加索引提示可以避免对订单进行全表扫描从而产生一个类似于大型系统中使用的执行计划尽管它在这里可能不是特别有效。 1.2.9 USE_NL_WITH_INDEX Hint 使用语法 /* USE_NL_WITH_INDEX ( [ queryblock ] tablespec [ indexspec [ indexspec ]... ] ) */ 介绍 USE_NL_WITH_INDEX提示指示优化器使用指定的表作为内部表通过嵌套循环联接将指定的表联接到另一个行源。例如 SELECT /* USE_NL_WITH_INDEX(l item_product_ix) */ *FROM orders h, order_items lWHERE l.order_id h.order_idAND l.order_id 2400;以下条件适用 如果没有指定索引那么优化器必须能够使用至少有一个连接谓词的索引作为索引键。如果指定了索引那么优化器必须能够将该索引与至少一个连接谓词一起用作索引键。 1.3 查询块查询块Hint对单个查询块进行操作
1.3.1 STAR_TRANSFORMATION Hint 使用语法 /* STAR_TRANSFORMATION [ ( queryblock ) ] */ 介绍 STAR_TRANSFORMATION提示指示优化器使用使用了转换的最佳计划。如果没有提示优化器可能会做出查询优化决策使用没有转换时生成的最佳计划而不是转换后查询的最佳计划。例如 SELECT /* STAR_TRANSFORMATION */ s.time_id, s.prod_id, s.channel_idFROM sales s, times t, products p, channels cWHERE s.time_id t.time_idAND s.prod_id p.prod_idAND s.channel_id c.channel_idAND c.channel_desc Tele Sales;即使指定了提示也不能保证转换会发生。只有在合理的情况下优化器才会生成子查询。如果没有生成子查询则没有已转换的查询并且使用未转换查询的最佳计划而不管提示如何。 1.3.2 UNNEST Hint 使用语法 /* UNNEST [ ( queryblock ) ] */ 介绍 UNNEST提示指示优化器取消嵌套并将子查询的正文合并到包含它的查询块的正文中从而允许优化器在评估访问路径和连接时将它们放在一起考虑。 在取消嵌套子查询之前优化器首先验证语句是否有效。然后语句必须通过启发式和查询优化测试。UNNEST提示指示优化器只检查子查询块的有效性。如果子查询块有效则启用子查询取消嵌套而不检查试探法或开销。 1.4 声明声明Hint适用于整个SQL语句
1.4.1 ALL_ROWS Hint ALL_ROWS提示指示优化器以最佳吞吐量(即最小的总资源消耗)为目标优化语句块。例如优化器使用查询优化方法来优化此语句以获得最佳吞吐量 SELECT /* ALL_ROWS */ employee_id, last_name, salary, job_idFROM employeesWHERE employee_id 107;如果在SQL语句中指定ALL_ROWS或FIRST_ROWS Hint并且如果数据字典没有关于该语句访问的表的统计信息则优化器使用默认统计值例如为这些表分配的存储来估计缺失的统计信息并随后选择执行计划。这些估计可能不如DBMS_STATS包收集的估计准确因此应该使用DBMS_STATS包收集统计信息。 如果为访问路径或联接操作指定提示以及ALL_ROWS或FIRST_ROWS提示则优化器会优先考虑提示指定的访问路径和联接操作。 1.4.2 FIRST_ROWS Hint FIRST_ROWS提示指示Oracle优化单个SQL语句以获得快速响应选择最有效地返回前n行的计划。对于整数指定要返回的行数。 例如优化器使用查询优化方法来优化以下语句以获得最佳响应时间 SELECT /* FIRST_ROWS(10) */ employee_id, last_name, salary, job_idFROM employeesWHERE department_id 20;在本例中每个部门都包含许多员工。用户希望尽快显示部门20的前10名雇员。 优化器在DELETE和UPDATE语句块以及包含任何阻塞操作如排序或分组的SELECT语句块中忽略此提示。此类语句无法优化以获得最佳响应时间因为Oracle数据库必须在返回第一行之前检索语句访问的所有行。如果在任何此类语句中指定此提示则数据库将优化以获得最佳吞吐量。 每篇文章我都认真对待只求质量不求数量所以博主大概产出一篇文章需要4天到7天这篇文章从构思到发布用了10天所以真心不容易觉得写的好的小伙伴请不吝自己的小手进行一键三连点赞、收藏、加关注哦。