为什么这个hql比使用标准快得多?

时间:2011-08-03 16:29:55

标签: sql performance sql-server-2000

我正在使用nhibernate作为ORM。我的一个选择是令人难以置信的缓慢。问题是,生成sql需要很长时间。我确定这不是sql查询本身很慢,因为我用sql profiler定时查询本身。并且它表明在开始执行nhibernate代码和实际发送到db的查询之间存在~15秒的差距。生成的SQL查询本身就像我预期的那样快。

选择代码(在存储库中)如下

public IEnumerable<Document> GetAllDocumentsReadyForDeletion()
{
    return from doc in _session.Query<Document>()
           where doc.StorageType == 'D'
           select doc;
}

我也尝试过:

return _session.CreateCriteria<Document>()
        .Add(Restrictions.Eq("StorageType", 'D'))
        .List<Document>();
等等(对吗?)。但是,它们的执行速度大致相同(缓慢,如15秒生成sql查询)

然而,这样做的速度和我想要的一样快,我不知道为什么:

return _session.CreateQuery(
        "from Document doc where doc.StorageType = 'D'")
        .List<Document>();

我真的想使用linq来nhibernate版本。知道为什么代码表现不同吗? (如果您需要更多详细信息,请询问!)

EDIT1

哦,伙计,我犯了一个愚蠢的错误或是什么..我错误地读取了sql profiler中错误的列.. ehm,前两个的实际执行时间是~18秒,第三个是~0秒。我试图找到sql atm的差异......

EDIT2

这实际上成了一个完全不同的问题。生成的查询几乎完全相同,除了前两个被包装在“exec sp_executesql”中

现在我用查询分析器跟踪了这一点,慢速查询只有一步:

clustered index scan.

快速查询有两个步骤:

Index seek
Bookmark lookup

有这样的经历吗?

2 个答案:

答案 0 :(得分:1)

他们实际上生成了不同的sql。其中一个使用索引,而其中一个没有。这就是为什么。为什么其中一个使用索引而另一个不满足下一个问题。

(简体)生成的SQL

快速版:

SELECT Id, Name FROM documents WHERE StorageType = 'D'

慢速版本(linq和条件)(从内存atm键入,稍后会检查):

sp_execsql N'SELECT Id, Name FROM documents WHERE StorageType = @p0', N'@p0 nchar(1)', N'D'

请注意,'StorageType'的类型为varchar(1)。 This博客文章解释了为什么这很慢

  

这里的问题是@p0作为NCHAR(1)(也就是Unicode字符)传递,该列与非Unicode的列索引不匹配。这就是索引扫描。

显然,此表上的索引扫描大约需要17秒。

答案 1 :(得分:0)

它们是NHibernate中的不同路径,以获取相同的数据。他们使用不同的代码构造查询。有关NHibernate的linq提供程序的问题的讨论。我最后编写了自己的LINQ提供程序,将LINQ引入NHibernate,只在第二个示例中创建字符串,然后使用它来获取数据。