【问题标题】:Why is this hql so much faster than using criteria?为什么这个 hql 比使用标准快得多?
【发布时间】:2011-10-19 06:46:10
【问题描述】:

我使用 nhibernate 作为 ORM。我的选择之一是令人难以置信的慢。问题是,生成 sql 需要很长时间。我确定不是 sql 查询本身很慢,因为我使用 sql profiler 对查询本身进行了计时。它表明在开始执行 nhibernate 代码和实际发送到数据库的查询之间存在约 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>();

wich 是等价的(对吗?)。但是,它们的性能大致相同(很慢,比如生成 sql 查询需要 15 秒)

但是,它的执行速度与我希望的一样快,但我不知道为什么:

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

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

编辑1

哦,伙计,我犯了一个愚蠢的错误还是什么..我错误地读取了 sql profiler 中的错误列.. 嗯,前两个的实际执行时间约为 18 秒,第三个约为 0 秒。我正在尝试查找 sql atm 中的差异...

编辑2

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

现在我用查询分析器跟踪了一下,慢查询有一个步骤:

clustered index scan.

快速查询分两步:

Index seek
Bookmark lookup

有类似的经验吗?

【问题讨论】:

  • "生成 sql 需要很长时间" -> 使用 SQL 分析器看不到...
  • @Mauricio 我的意思是我在执行代码示例之前打印了一条消息,同时我正在使用 SQL 分析器监视 sql 服务器。这样我可以看到从开始执行语句到将 sql 查询发送到 sql server 需要很长时间。我澄清了我的问题。

标签: sql performance sql-server-2000


【解决方案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 秒。

【讨论】:

  • 我实际上使用 type="AnsiChar" 解决了它(见stackoverflow.com/questions/1306774/…
  • +1 很有趣,没想到会导致这样的延迟!您能否发布生成的不同 SQL 查询?
  • 大概只是做SELECT Id, Name FROM documents WHERE StorageType = N'D' 也会很慢?我在 Java 世界中遇到过很多次这个问题......它被重写为WHERE cast(storagetype as nchar) = N'D' 或类似的地方,这不再是简单的 storagetype 相等检查,因此没有索引。
  • @araqnid 哈,你说得对。但这让我再次思考。这是否意味着我在 nhibernate 中发现了一个错误?因为它实际上应该使用来自 hql 的N'D' 生成?
  • @Mr Happy:嗯,N'D' 格式是特定于 SQL Server 的东西(至少,不是通用的 SQL 东西),所以让方言导致它会有点痛苦发生。但是,如果您使用参数化查询,它(有效地)会这样做。
【解决方案2】:

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

【讨论】:

  • 但 Criteria 方法所用的时间几乎与 LINQ 版本一样长。我认为标准 api 相当成熟;我一定是做错了什么xD
  • @Mr.很高兴我没有注意到 NHibernate Criteria 不是 LINQ 的 Method 版本。
  • “我最终编写了自己的 LINQ 提供程序”-> 为什么不为修复 NH LINQ 提供程序做出贡献呢?看来你对此很了解!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-21
  • 2015-02-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多