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

发布于 2024-11-28 00:17:06 字数 1299 浏览 1 评论 0原文

我使用 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>();

这是等效的(对吗?)。然而,它们的执行速度大致相同(很慢,比如生成 sql 查询需要 15 秒)

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

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

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

Edit1

天哪,我犯了一个愚蠢的错误还是什么..我错误地在sql分析器中读取了错误的列..嗯,实际执行时间前两个约为 18 秒,第三个约为 0 秒。我试图找到 sql atm 中的差异...

Edit2

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

现在我用查询分析器对此进行了跟踪,慢速查询有一个步骤:

clustered index scan.

快速查询有两个步骤:

Index seek
Bookmark lookup

有类似的经历吗?

I'm using nhibernate as ORM. And one of my selections is incredible slow. The thing is, that it takes a long time to generate the sql. I'm sure it's not the sql query itself that's slow, because I timed the query itself with sql profiler. And it showed that there is a ~15 sec gap between starting to execute the nhibernate code, and the query being actually sent to the db. The generated SQL query itself is as fast as I'd expect it to be.

The selection code (in a repository) is as follows

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

I also tried:

return _session.CreateCriteria<Document>()
        .Add(Restrictions.Eq("StorageType", 'D'))
        .List<Document>();

wich is the equivalent (right?). However, they both perform about the same (slow, like 15 secs to generate the sql query)

This however, performs as fast as I want it to be, and I have no clue why:

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

I really want to use the linq to nhibernate version. Any idea why the code performs differently? (If you need more details, just ask!)

Edit1

Oh man, did I make a stupid mistake or what.. I mistakenly read the wrong column in the sql profiler.. The ehm, actual execution time for the first two are ~18 seconds, the 3rd is ~0 secs. I'm trying to find the differences in sql atm...

Edit2

This is actually becoming a whole different question. The resulting queries are almost exactly the same, except for that the first two are wrapped inside a "exec sp_executesql"

Now I've traced this a bit with query analyser, and the slow query has one step:

clustered index scan.

The fast query has two steps:

Index seek
Bookmark lookup

Any experiences with something like this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦毁影碎の 2024-12-05 00:17:06

他们实际上生成不同的sql。其中之一使用索引,而其中之一则不使用索引。这就是原因。为什么其中一个使用索引而另一个不使用下一个问题。

(简化)生成的 SQL

快速版本:

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

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

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

注意“StorageType”的类型为 varchar(1)。 这篇博客文章解释了为什么速度很慢

这里的问题是 @p0 作为 NCHAR(1) (又名 Unicode 字符)传递,它与非 Unicode 列的索引不匹配。本例为索引扫描。

显然,对该表进行索引扫描大约需要 17 秒。

They actually generate different sql. One of wich uses the index, and one of wich doesn't. That's why. Why one of those uses the index and the other doesn't is content for a next question.

(Simplified) Generated SQL

Fast version:

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

Slow version (both linq and criteria)(typing from memory atm, will check later):

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

note that 'StorageType' is of type varchar(1). This blog post explains why this is slow

The problem here is that @p0 is passed as NCHAR(1) (aka a Unicode char) which does not match the index of the column with is non-Unicode. This cases the index scan.

Apparently, an index scan takes about 17 secs on this table.

后eg是否自 2024-12-05 00:17:06

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

They are different paths in NHibernate to get the same data. They construct the queries using different code. There are discussions about the problem with NHibernate's linq provider. I ended up writing my own LINQ provider to give me LINQ into NHibernate that just creates the string in the second example then uses that to get the data.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文