2

嗨,我在尝试在 oracle 中找到绑定感知游标匹配的简单解释时遇到了一些麻烦。绑定感知游标匹配基本上是让 Oracle 随着时间的推移监视带有绑定变量的查询,并查看使用某些时 CPU 是否增加变量。然后这样做几乎会生成一个更合适的执行计划,比如全表扫描,然后将查询标记为绑定感知,然后下次执行查询时可以选择两个执行计划吗?任何帮助将不胜感激!干杯!

4

1 回答 1

5

在最简单的情况下,假设您有一张ORDERS桌子。该表中有一个status列。只有少数status价值观,有些非常非常受欢迎,而另一些则非常罕见。假设该表有 1000 万行。出于我们的目的,假设 93% 是“完成”,5% 是“取消”,剩下的 2% 分布在跟踪订单流的 8 个不同状态(未完成、完成、履行中、运输中等)之间。 )。

如果您的表有最基本的统计信息,优化器就知道有 1000 万行和 10 个不同的状态。它不知道某些status值比其他值更受欢迎,因此它猜测每个状态对应于 100 万行。所以当它看到类似的查询时

SELECT *
  FROM orders
 WHERE status = :1

它猜测无论绑定变量值如何,它都需要从表中获取 100 万行,因此它决定使用全表扫描。

现在,有人想知道为什么当 Oracle 请求少数orders处于 IN TRANSIT 状态的数据库时,Oracle 会愚蠢地进行全表扫描——显然,索引扫描在那里更可取。该人意识到优化器需要更多信息才能了解某些status值比其他值更受欢迎,因此人类决定收集直方图(有些选项会导致 Oracle 自动在某些列上收集直方图,但我忽略了那些试图保持故事简单的选项)。

一旦收集了直方图,优化器就知道该status值高度偏斜——有很多 COMPLETED 订单,但很少有 IN TRANSIT 订单。如果它看到一个使用文字而不是绑定变量的查询,即

SELECT *
  FROM orders
 WHERE status = 'IN TRANSIT'

对比

SELECT *
  FROM orders
 WHERE status = 'COMPLETED'

那么优化器很容易决定在第一种情况下使用索引,在第二种情况下使用表扫描。但是,当您有一个绑定变量时,优化器的工作就更加困难了——它应该如何确定是使用索引还是进行表扫描......

Oracle 的第一个解决方案被称为“绑定变量窥视”。在这种方法中,当优化器看到类似

SELECT *
  FROM orders
 WHERE status = :1

它知道(因为直方图 on status)查询计划应该取决于为绑定变量传入的值,Oracle “窥视”传入的第一个值以确定如何优化语句。如果第一个绑定变量值为“IN TRANSIT”,则将使用索引扫描。如果第一个绑定变量值为“COMPLETE”,则将使用表扫描。

在很多情况下,这非常有效。许多查询实际上只对非常流行或非常稀有的值有意义。在我们的示例中,几乎不可能有人真正想要一份所有 900 万个 COMPLETE 订单的列表,但有人可能想要一份处于各种临时状态之一的几千个订单的列表。

但是绑定变量窥视在其他情况下效果不佳。如果您有一个系统,其中应用程序有时会绑定非常流行的值,有时会绑定非常稀有的值,那么您最终会遇到应用程序性能很大程度上取决于谁先运行查询的情况。如果第一个运行查询的人使用非常稀有的值,则会生成并缓存索引扫描计划。如果运行查询的第二个人使用非常常见的值,则将使用缓存的计划,并且您将获得一个耗时的索引扫描。如果角色互换,第二个人使用稀有值,获取执行全表扫描的缓存计划,并且必须扫描整个表以获取他们感兴趣的几百行。如果星期一早上下雨,他们需要在下午重新启动数据库

绑定感知游标匹配是绑定变量窥视问题的解决方案。现在,当 Oracle 看到查询时

SELECT *
  FROM orders
 WHERE status = :1

并看到有一个直方图status这表明某些值比其他值更常见,它足够聪明以使该光标“具有绑定意识”。这意味着当您绑定 IN FULFILLMENT 的值时,优化器足够聪明,可以断定这是稀有值之一并为您提供索引计划。当您绑定 COMPLETE 的值时,优化器足够聪明,可以断定这是常见值之一,并为您提供表扫描计划。因此,优化器现在知道同一查询的两个不同计划,当它看到一个新的绑定值(如 IN TRANSIT)时,它会检查该值是否与它之前看到的其他值相似,并为您提供现有计划之一或创建另一个新计划。在这种情况下,它将决定 IN TRANSIT 大致与 IN FULFILLMENT 一样常见,因此它重新使用索引扫描的计划,而不是生成第三个查询计划。希望这会导致每个人都获得他们喜欢的计划,而不必在每次绑定变量值更改时生成和缓存查询计划。

当然,在现实中,还有很多额外的警告、极端案例、注意事项和复杂性,我有意(和无意地)在这里掩饰。但这是优化器试图完成的基本思想。

于 2014-03-18T23:31:34.603 回答