sql-server - SQL 没有优化我的参数化查询

标签 sql-server sql-server-2008

我有这样的查询:

select top(10) * from dbo.myTable where DisplayName like 'farm%'

这导致在 DisplayName 上进行索引查找,因为通配符在尾部。但是,当我这样做时情况并非如此:

declare @val varchar(200) = 'farm'
select top(10) * from dbo.myTable where DisplayName like @val + '%'

或者这个:

declare @val varchar(200) = 'farm%'
select top(10) * from dbo.myTable where DisplayName like @val

在这些情况下,SQL 回退到慢得多的索引扫描操作。所定位的值是一个在运行时提供的参数,因此显然我不能仅将第一个查询用于我的目的。

有什么办法可以:

  1. 确保 SQL 索引查找值,并且
  2. 将此逻辑存储在预编译的存储过程中。查询需要很快,所以我不想不得不求助于每次执行都强制重新编译的方法(即使编译开销 + 索引查找仍然比索引扫描快)

我知道通配符的存在与否会影响执行计划,但 SQL 似乎不理解通配符总是被使用,即使您将它连接到值,如查询 #2 中一样。

最佳答案

SQL Server can use a range seek for these queries (在变量包含前导通配符的情况下,范围最终就是整个索引)。

如果在这种情况下没有选择这样做,可能是因为变量的使用意味着它没有准确估计选择性。您可以尝试添加 OPTION (RECOMPILE) 提示,以便它考虑实际变量值。

关于sql-server - SQL 没有优化我的参数化查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12338903/

相关文章:

sql - 如何在sql server中对行号进行内连接

sql-server - 如何优雅地写一个 SQL ORDER BY(在内联查询中无效),但聚合 GROUP BY 需要?

SQL - 如果记录为 NULL 因为表中不存在记录,则为 CASE 语句

c# - 为什么 DBNull.Value 需要正确的 SqlDbType?

c# - Entity Framework 迁移重命名表和列

sql - 检查表 1 的某一列的所有单词是否存在于表 2 的其他列中

c# - 操作数类型冲突 : varchar is incompatible

sql - 将 "Arnold Schwarzenegger"和 "Hasta la vista baby"插入到这两个空 SQL 表中,我的 SQL 语句是什么?

sql - 在存储过程中验证密码

c# - 如何保留数据的旧值和新值?