什么是“SQL-Hints”?

时间:2008-11-04 14:15:28

标签: sql hibernate orm

我是ORM解决方案的倡导者,我不时会举办关于Hibernate的研讨会。

在谈论框架生成的SQL时,人们通常会开始谈论他们需要如何使用“提示”,而这对于ORM框架来说是不可能的。

通常类似于:“我们尝试过Hibernate。它在开始时看起来很有前途,但是当我们在非常复杂的生产数据库中放松它时,它就会崩溃,因为我们无法应用提示!”。

但是当被问到一个具体的例子时,那些人的记忆突然变得不那么清楚......

我通常感到害怕,因为整个“提示” - 主题对我来说听起来像伏都教...... 那么有人可以开导我吗? SQL-hints或DB-Hints是什么意思?

我唯一知道的,就是某种“提示式”是SELECT ... FOR UPDATE。但这得到了Hibernate-API的支持......

5 个答案:

答案 0 :(得分:10)

SQL语句,尤其是复杂的语句,实际上可以由数据库引擎以任意数量的方式执行(首先读取连接中的哪个表,根据许多不同的参数使用哪个索引等)。 / p>

经验丰富的dba可以使用提示鼓励数据库引擎在生成执行计划时选择特定方法。在对特定查询进行大量测试和分析之后,您通常只需要执行此操作(因为数据库引擎通常非常擅长确定最佳执行计划)。

这里有一些特定于MSSQL的讨论和语法:
http://msdn.microsoft.com/en-us/library/ms181714.aspx

修改:在http://geeks.netindonesia.net/blogs/kasim.wirama/archive/2007/12/31/sql-server-2005-query-hints.aspx

处添加了一些其他示例

答案 1 :(得分:8)

查询提示用于在默认情况下不生成合理的查询计划时指导查询优化器。首先,查询优化器的一个小背景:

数据库编程与几乎所有其他软件开发不同,因为它具有机械组件。磁盘寻道和旋转延迟(等待特定扇区到达磁盘头下)与CPU相比非常昂贵。不同的查询解析策略将导致不同的I / O量,通常是完全不同的量。正确或错误可能会对查询的性能产生重大影响。有关查询优化的概述,请参阅This paper.

SQL是声明性的 - 您指定查询的逻辑并让DBMS弄清楚如何解决它。现代的基于成本的查询优化器(某些系统,例如Oracle还保留了用于向后兼容的遗留查询优化器)将对查询运行一系列转换。它们保持语义等同,但在操作的顺序和选择上有所不同。根据在表格上收集的统计数据(密钥的大小,分布直方图),优化程序计算每个查询计划所需工作量的估计值。它选择了最有效的计划。

基于成本的优化是启发式的,并且依赖于准确的统计数据。随着查询复杂性的增加,启发式方法可能会产生错误的计划,这可能会非常低效。

在这种情况下可以使用查询提示强制查询计划中的某些策略,例如连接类型。例如,对于通常返回非常小的结果集的查询,您可能希望强制嵌套循环连接。您可能还希望强制执行某些表的连接顺序。

O / R映射器(或任何生成SQL的工具)生成自己的查询,通常没有提示信息。如果此查询运行效率低下,则选项有限,其中一些选项为:

  • 检查表上的索引。可能你可以添加一个索引。某些系统(例如Oracle的最新版本)允许您跨多个表索引连接。

  • 某些数据库管理系统(同样,Oracle会想到)允许您手动将查询计划与特定查询字符串相关联。查询计划由查询的哈希值缓存。如果查询是参数化的,则基本查询字符串是常量,并将解析为相同的哈希值。

  • 作为最后的手段,您可以修改数据库架构,但只有在您控制应用程序时才可以这样做。

如果您控制SQL,则可以提示查询。在实践中,实际上需要这样做是相当罕见的。具有复杂数据库模式的O / R映射器上更常见的故障模式是它们使得难以表达复杂的查询谓词或对大量数据执行复杂操作。

我倾向于提倡将O / R映射器用于适合的98%的工作,并放到存储过程中,它们是适当的解决方案。如果您确实需要提示查询,那么这可能是合适的策略。除非您的应用程序有某些不寻常之处(例如某种DSS),否则您应该这样做 只需要在少数情况下逃离O / R映射器。你也可以 查找(再次,一个例子是DSS工具使用聚合数据),O / R映射器实际上不是应用程序的适当策略。

答案 2 :(得分:4)

虽然HINTS正如其他答案所描述的那样,但您应该只在罕见的研究环境中使用它们。 10个HINT中的9次将导致查询计划不佳。除非你真的知道自己在做什么,否则不要使用它们。

答案 3 :(得分:3)

所有现代RDBMS都有某种查询优化器,可以计算最佳查询计划,这是执行SQL查询所需的读/写操作序列。

有时计划可能不是最理想的,因此RDBMS设计者在SQL中包含“提示”。提示是可以嵌入到SQL中的指令,它们会影响查询优化器。通过提示,您可以指示查询优化器,例如它应该使用哪些索引,应该从表中读取数据的顺序,......

因此,通过提示,您可以解决查询优化器无法自行解决的一些瓶颈。

例如,这里是Oracle hints的列表。

答案 4 :(得分:3)

没有“优化的SQL代码”,因为SQL代码永远不会被执行。

优化程序将SQL代码转换为执行计划。优化器将使用它所选择的信息(除其他外)。

  • 涉及表格的顺序
  • 每个涉及的表的连接方法(嵌套/合并/哈希)
  • 如何访问表的数据(使用书签查找/直接索引访问的直接表访问/索引)(扫描/搜索)
  • 应该使用并行性,何时结束并行性(聚集流)

查询提示允许程序员覆盖(在大多数情况下)或礼貌地(在其他情况下)建议优化器的选择。

查询提示可以让你强制关闭并行性,强制所有连接实现为嵌套循环,强制将一个索引用于另一个...作为一些例子。

由于优化器 非常好 ,如果一个人超越优化器,通常会要求一个非最佳计划。当优化器没有所需的信息来做出正确的选择时,最好提供查询提示。

我使用查询提示的一个地方是表变量。优化器假定表变量有0行,因此优化器总是使用嵌套循环(少量行的最佳连接实现)连接表变量。如果我有一个大的表变量 - 已经以有利的方式为合并连接排序,我可以通过应用查询提示来指定合并连接。