假设我有一个名为项目
的表,其中有一列名为预算
,具有标准的B-Tree索引。该表有50,000个项目,只有1%的项目的预算超过100万。如果我运行以下SQL查询:
SELECT * From Projects WHERE Budget > 1000000;
规划器将使用索引范围扫描Budget
从堆表中获取行。但是,如果我使用以下查询:
SELECT * From Projects WHERE Budget > 50;
规划器很可能会对该表进行顺序扫描,因为它知道这个查询最终将返回大部分或全部行,并且没有理由将索引的所有页面加载到内存中。 现在,假设我运行以下查询:
SELECT * From Projects WHERE Budget > :budget;
当我将参数:budget
传递到数据库时,查询语句会被缓存,但是无法推断出基数数据。实际上,大多数数据库会假设分布均匀,并且缓存的查询计划也会反映这一点。这让我感到惊讶,因为通常当你阅读关于绑定参数的好处时,主题是防止SQL注入攻击。
显然,如果生成的查询计划相同,则这可能会提高性能,因为不需要编译新计划,但如果:budget
的值差异很大,则可能会降低性能。
我的问题:为什么绑定参数在生成和缓存查询计划之前不被解析?现代数据库难道不应该为查询生成最佳计划吗?这应该意味着查看每个参数的值并获取准确的索引统计信息。
注意:这个问题可能不适用于mySql,因为mySql不缓存SQL计划。但是,我对为什么Postgres、Oracle和MS SQL也是如此感兴趣。
Budget > 1000000
比Budget > 50
返回了多少行。 - AndreKR