Sql server sp_executesql不使用索引?

Sql server sp_executesql不使用索引?,sql-server,nhibernate,count,Sql Server,Nhibernate,Count,我在我的web应用程序中使用nhibenerate,在生成的sp_execute中使用索引时遇到问题。我的表有2.1亿条记录,查询速度非常慢 首先,生成的列“kolumna1”类型存在问题。在数据库中,我有一列varchar,但nHibernate生成了nvarchar。我通过在代码中添加特殊属性来解决这个问题,强制使用varchar。在那之后,sp_开始使用索引,一切都是正确的。现在问题又出现了,sp_executesql需要10分钟才能完成。当我选中普通查询(没有sp_executesql)

我在我的web应用程序中使用nhibenerate,在生成的sp_execute中使用索引时遇到问题。我的表有2.1亿条记录,查询速度非常慢

首先,生成的列“kolumna1”类型存在问题。在数据库中,我有一列varchar,但nHibernate生成了nvarchar。我通过在代码中添加特殊属性来解决这个问题,强制使用varchar。在那之后,sp_开始使用索引,一切都是正确的。现在问题又出现了,sp_executesql需要10分钟才能完成。当我选中普通查询(没有sp_executesql)时,只花了1s。我检查了两者的执行计划:sp_executesql没有使用索引,而普通查询使用索引。在不改变索引的情况下,我将varchar修改回nvarchar,sp_execute在1s内完成(使用索引)。有人知道我在哪里出错了吗?为什么执行计划对于如此小的变化是不同的?如何修复它

这里我附加了更多的代码。以防有人需要

sp_executesql与varchar(8000)

在查询的执行计划下方:从[dbo].[tabela1]中选择count(*),其中[kolumna1]类似于N“%501096109%” 你能试试这个吗:

(1) 运行以下SQL语句:

select * from sys.dm_exec_cached_plans
cross apply sys.dm_exec_sql_text(plan_handle) t
(2) 使用最后一列查找第一个查询的SQL。它不包含sp_executesql,但将从参数列表开始,最后一个是varchar。获取计划句柄,并在以下语句中使用它:

dbcc freeproccache (<your_plan_handle>)
dbcc freeproccache()

然后重试查询1。

Sql Server查询优化器可以选择在以下情况下使用索引搜索:

  • 除了LIKE之外,还有另一个过滤器谓词。它应该是一个精确的搜索,或者至少是一个可搜索的谓词
  • 表非常大(数百万行)
  • 但当使用显式类型转换时,无法执行查找操作-不同的排序规则/数据类型。 另一件您无法控制此行为和查询计划的事情是,不同的谓词集可能会有所不同。为此,您需要使用提示FORCESEEK(版本2008+)。您可以在此处找到信息:

    这可能会有所帮助:此查询将无法对kolumna1使用索引搜索。原因是你的模式中有一个领先的%。你能提供使用你的一个索引的非计数查询吗?对Jamie Ide说:我们已经尝试过这种方法,在nhibernate和Databaseto muhmu中都有varchar:我们一直在使用计数查询。我的问题犯了一个错误。我已经修复了它,并为nvarchar和varchar查询添加了执行计划。您是说生成第一个执行计划的查询与您给出的查询相同,只是没有使用sp_executesql?你能核实一下吗?因为该计划在IX_tabela1_kolumna1上包含一个索引查找,但是,正如我前面所说的,您的查询包含一个不允许这样做的kolumna1模式。另外,你能提供整个第一个计划吗?它被砍了一点。如果您能将实际使用的SQL放在每个计划之上,那也太好了。谢谢您的回复。好的,但是如何强制NHibernate使用提示呢?我们的查询条件与包含的参数具有相同的排序规则/数据类型。对于我在sp_executeSQL选项(重新编译)中的查询后进行的测试,它可以工作。请查看
    exec sp_executesql N'SELECT count(*) as y0_ FROM tabela1 this_  
    WHERE this_.kolumna3 in (@p2, @p3) and ((this_.kolumna2 >= @p0 and this_.kolumna2 <= @p1))  
    and ( this_.kolumna1 like @p4)',N'@p0 datetime,@p1 datetime,@p2 int,@p3 int,@p4 varchar(8000)',  
    @p0='2013-01-08 14:38:00' ,@p1='2013-02-08 14:38:00',@p2=341,@p3=342,@p4='%501096109%'  
    --Declare @p0 datetime  
    --set @p0 = '2013-01-08 14:38:00'  
    --Declare @p1 datetime  
    --set @p1 = '2013-02-08 14:38:00'  
    --Declare @p2 int  
    --set @p2 = 341  
    --Declare @p3 int  
    --set @p3 = 342  
    --Declare @p4 varchar(8000)  
    --set @p4 = '%501096109%'  
    --SELECT count(*) as y0_  
     --FROM tabela1 this_  
     --WHERE ((this_.kolumna2 >= @p0 and  
     --this_.kolumna2 <= @p1)) and  
     --(this_.kolumna3 in (@p2, @p3) and this_.kolumna1 like @p4)
    
    CREATE TABLE [dbo].[tabela1](
    [id] [bigint] NOT NULL,
    [kolumna1] [varchar](128) NOT NULL,
    [kolumna2] [datetime] NOT NULL,
    [kolumna3] [int] NOT NULL,
    CONSTRAINT [PK__tabela1__4F7CD00D] PRIMARY KEY CLUSTERED 
    (
        [id] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    
    CREATE NONCLUSTERED INDEX [ind_tabela1_ kolumna2] ON [dbo].[tabela1] 
    (
        [kolumna2] ASC
    
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    GO
    
    CREATE NONCLUSTERED INDEX [ind_ tabela1_ kolumna3] ON [dbo].[ tabela1] 
    (
        [kolumna3] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    GO
    
    CREATE NONCLUSTERED INDEX [IX_ tabela1_ kolumna1] ON [dbo].[ tabela1] 
    (
        [kolumna1] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    GO
    CREATE NONCLUSTERED INDEX [IX_ tabela1_ kolumna2_ kolumna3] ON [dbo].[ tabela1] 
    (
        [kolumna2] ASC,
        [kolumna3] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    GO
    CREATE NONCLUSTERED INDEX [IX_ tabela1_ kolumna3_ kolumna2_id_ kolumna1] ON [dbo].[ tabela1] 
    (
        [kolumna3] ASC,
        [kolumna2] ASC,
        [id] ASC,
        [kolumna1] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    GO
    
    select * from sys.dm_exec_cached_plans
    cross apply sys.dm_exec_sql_text(plan_handle) t
    
    dbcc freeproccache (<your_plan_handle>)