gpt4 book ai didi

sql - SQL 绑定(bind)参数会影响性能吗?

转载 作者:行者123 更新时间:2023-11-29 11:26:21 24 4
gpt4 key购买 nike

假设我有一个名为 Projects 的表,其中包含一个名为 Budget 的列,并带有标准 B-Tree 索引。该表有 50,000 个项目,其中只有 1% 的预算超过一百万。如果我运行 SQL 查询:

SELECT * From Projects WHERE Budget > 1000000;

规划器将在 Budget 上使用索引范围扫描来从堆表中获取行。但是,如果我使用查询:

SELECT * From Projects WHERE Budget > 50;

规划器很可能会在表上执行顺序扫描,因为它会知道此查询无论如何最终都会返回大部分或所有行,并且没有理由将索引的所有页面加载到内存中。

现在,假设我运行查询:

SELECT * From Projects WHERE Budget > :budget;

其中 :budget 是传递到我的数据库中的绑定(bind)参数。根据我的阅读,上面的查询将被缓存,并且无法推断出任何关于基数的数据。事实上,大多数数据库只会假设均匀分布,缓存的查询计划会反射(reflect)这一点。这让我感到惊讶,因为通常当您阅读有关绑定(bind)参数的好处时,它是关于防止 SQL 注入(inject)攻击的主题。

显然,如果生成的查询计划相同,这可以提高性能,因为不必编译新计划,但也可能损害性能如果 :budget 的值变化很大。

我的问题:为什么绑定(bind)参数在查询计划生成和缓存之前没有解析?现代数据库不应该努力为查询生成最佳计划,这应该意味着查看每个参数的值并获得准确的索引统计信息吗?

注意:这个问题可能不适用于 mySql,因为 mySql 不缓存 SQL 计划。但是,我感兴趣的是为什么在 Postgres、Oracle 和 MS SQL 上会出现这种情况。

最佳答案

具体对于 Oracle,这取决于。

很长一段时间(至少 9i),Oracle 支持绑定(bind)变量查看。这意味着第一次执行查询时,优化器会查看绑定(bind)变量的值并将其基数估计基于第一个绑定(bind)变量的值。在大多数查询执行将具有返回类似大小结果的绑定(bind)变量值的情况下,这是有意义的。如果 99% 的查询都使用较小的预算值,那么第一次执行很可能会使用较小的值,因此缓存的查询计划将适用于较小的绑定(bind)变量值。当然,这意味着当您确实指定了一个大的绑定(bind)变量值时(或者,更糟糕的是,如果您运气好并且第一次执行时使用了一个大值),您将获得不太理想的查询计划。

如果您使用的是 11g,Oracle 可以使用 adaptive cursor sharing .这允许优化器为单个查询维护多个查询计划,并根据绑定(bind)变量值选择适当的计划。不过,随着时间的推移,这可能会变得相当复杂。如果您有一个包含 N 个绑定(bind)变量的查询,优化器必须弄清楚如何将 N 维空间划分为不同绑定(bind)变量值的不同查询计划,以便弄清楚何时以及是否为新的查询重新优化查询一组绑定(bind)变量值以及何时简单地重用早期计划。许多工作最终在夜间维护窗口期间完成,以避免在生产日产生这些成本。但这也带来了以下问题:DBA 希望给予数据库多大的自由来随着时间的推移发展计划,以及 DBA 想要控制计划的程度,以便数据库不会突然开始选择一个糟糕的计划,从而导致一些主要系统在随机的一天缓慢地爬行。

关于sql - SQL 绑定(bind)参数会影响性能吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12286313/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com