问题标签 [select-n-plus-1]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
3 回答
488 浏览

sql - 哪种是避免 n+1 问题的最快执行方法,为什么?

我希望添加一些实用方法来帮助避免遗留应用程序中的许多n+1 问题

常见的模式是这样的:

检索到ClassA记录实例的集合

然后子实例被惰性检索:

这会导致 n+1 选择问题。大多数情况下,这不是一个主要问题,因为ClassA在不经常点击的页面上只检索了几个实例,但在越来越多的地方,这个 n+1 问题会导致页面在应用程序扩展时变得太慢。

我正在寻找替换此应用程序的现有数据访问代码的一部分,以便一起检索ClassA实例和实例。ClassB

我认为有3种方法可以做到这一点:

1)ClassA像我们现在一样获取实例,然后ClassB在一个聚合调用中获取实例:

这是两个单独的 DB 调用,动态 SQL 的查询计划将不可缓存(由于 ID 列表)。

2)ClassB使用子查询获取实例:

这也是两个数据库调用,并且必须对查询[table-A]进行两次评估。

3) 将所有实例放在一起并删除重复数据ClassA

这只是一个 DB 调用,但现在我们得到了[table-A]重复的内容——结果集会更大,将数据从 DB 发送到客户端的时间会更长。

所以实际上这是 3 种可能的妥协:

  1. 2 次数据库调用,无查询缓存
  2. 2 次数据库调用,复杂查询评估了两次
  3. 1 次数据库调用,显着更大的结果集

我可以为任何一对父子表测试这三种模式,但我有很多。我想知道的是哪种模式始终更快?更重要的是为什么?这些妥协之一是明显的性能杀手吗?

Linq、EF 和 NHibernate 等现有机制使用什么?

有没有比所有 3 更好的第 4 种方法?

0 投票
1 回答
286 浏览

nhibernate - 我无法避免这个选择 N+1

我有这个映射(它来自 Adventureworks,因为我在演示应用程序中使用它来进行自动分页收集)

以及以下(有限)查询:

员工联系导致的select N+1无法删除,怎么办?考虑映射也可以更改!

EDIT:我通过@cremor 添加了工作解决方案

这将避免这个问题。

0 投票
2 回答
1251 浏览

nhibernate - 如何避免 NHibernate N+1 使用复合键

编辑我为这个问题重新制作了整个项目。因此,我重新提出了这个问题。

我希望能够有效地避免 N+1 和笛卡尔连接将 4 级深度实体与第三级的复合键连接在一起。

我希望仅在几个查询中完成此操作,而不是延迟加载,而不仅仅是将所有表连接在一起。

A -(多)-> B -(多)-> C -(复合,单)-> D

就像是:

这是使用的代码 这是一个功能齐全的应用程序。我使用 NuGet 安装 Sqlite x86、StructureMap、NHProf、Fluent NH。

StructureMapServiceLocator:

应用程序注册表

列出实体:

程序(控制台):

0 投票
1 回答
775 浏览

c# - NHibernate Select N+1 and Recursive

I've got a couple of data classes:

So 1 RecordGroup is "connected" to several DataRecords, having several children (which again got children etc.) each of them having several Properties and Fotos. I need all the DataRecords including Children, Properties and Fotos according to a certain RecordGroup.

Doing this within raw SQL is a simple statement with a few joins, but when i try to do this with linq and nhibernate it results in 1500 Select N+1 Statements, and an enormous slowdown.

I already tried .FetchMany( x => x.Children );

How is it possible to get the whole "datatree" of 1 Recordgroup within 1 Query?

Thanks in advance!!!!

0 投票
1 回答
261 浏览

c# - 为什么相同的 NHibernate 查询在 WinForm 项目中的运行速度比 MSTest 单元测试慢一个数量级?

我有一个在生产环境中作为服务运行的应用程序,但我们使用简单的 GUI 进行了一些手动测试——其中几乎没有发生任何事情,它只是一个带有用于输入的文本框的包装器。

我最近更改了我的数据库模式并更新了我的映射以匹配,然后 GUI 突然在一个微不足道的情况下工作得非常缓慢。经过一些记录并多次运行后,发现新的瓶颈是这个查询:

重复地,该方法花费了 1:08 分钟(即使数据库中只有大约 300 个 FieldDefinitions)。到这个时候,我已经厌倦了手动重新运行 GUI,所以我编写了一个单元测试来执行完全相同的情况 - 但我无法重现减速。

我的测试调用了 GUI 使用相同输入执行的相同顶级对象。我希望这将在几乎相同的时间内运行。但是,当使用 MSTest 在 Visual Studio 中运行时,相同的查询只用了不到两秒的时间。那是时间的 1/30。它正在做完全相同的工作,只是速度要快得多。

我检查了是否可以使它们运行相同的东西:

  • 两种方法都产生相同数量的 SQL 语句。
  • 它似乎不是由 JITter 引起的(多次运行 GUI 而不重新启动它,同时一遍又一遍的结果)
  • 将其隔离以使其ISessionFactory对每个Refresh都使用全新的没有效果
  • 关闭日志记录(log4net)没有效果

将查询更改为急切加载孩子确实有效……有点:应用修复后,WinForms 应用程序的速度仅与单元测试的速度一样。单元测试的速度没有显着变化(十分之一秒)。

旧查询导致了select n+1问题:但 Winform 和 MSTest 运行中都存在该问题。因此,只有 WinForm 应用程序出现了明显的放缓。

我该如何解释?为什么只有 WinForm 应用程序在 Select N+1 查询期间会遭受巨大的减速?

0 投票
1 回答
673 浏览

linq - 为什么 SELECT N + 1 没有外键和 LINQ?

我有一个数据库,不幸的是没有真正的外键(我计划稍后添加,但现在不希望这样做以使迁移更容易)。我已经手动编写了映射到数据库以建立关系的域对象(按照本教程http://www.codeproject.com/Articles/43025/A-LINQ-Tutorial-Mapping-Tables-to-Objects),我'终于让代码正常运行了。但是,我注意到我现在遇到了 SELECT N + 1 问题。不是选择所有产品,而是使用以下 SQL 逐一选择它们:

控制器:

因为我不确定我的 LINQ 表达式是否正确,所以我尝试使用它,但我仍然得到 N+1:

域对象:

我试图从我的视图中注释掉所有内容,所以似乎没有任何影响。ViewModel 看起来很简单,所以不应该有任何东西。

在阅读本文时(http://www.hookedonlinq.com/LinqToSQL5MinuteOVerview.ashx),我开始怀疑这可能是因为我在数据库中没有真正的外键,并且我可能需要在我的代码中使用手动连接。那是对的吗?我该怎么办?我应该从我的域模型中删除我的映射代码还是我需要添加/更改它的东西?

注意:我已经删除了一些我认为与使其更清晰地解决这个问题无关的部分代码。如果缺少某些东西,请告诉我。

Products编辑:格特·阿诺德从Category被查询中一一解决了所有问题。但是我仍然遇到Products页面上显示的所有内容都被一一查询的问题。

这发生在我的视图代码中:

列表.cshtml:

ProductSummary.cshtml:

.First() 又是什么东西?我尝试了 .Take(1) 但无论如何我都无法选择 ID...

编辑:我尝试将一些代码添加到我的存储库以访问 DataContext 和此代码以创建 DataLoadOptions。但它仍然会为每个 ProductSub 生成一个查询。

虽然生成的 SQL 略有不同,但查询的顺序也不同。

对于选择 ProductSub 的查询,DataLoadOptions 代码会生成名为@x1的变量,如果没有这些变量,则变量名为@p0

对我的查询顺序的差异表明 DataLoadOptions 实际上正在做某事,但不是我所期望的。我期望它产生这样的东西:

0 投票
2 回答
965 浏览

java - 使用 JPA/Hibernate 构造函数表达式防止“n+1 选择”?

我有两个实体,ItemandData和一个 DTO 类ItemDataItemData包含Item并且Data没有 JPA 映射。为了检索填充的 ItemDatas 列表,我在 JPQL 中使用了构造函数表达式:

这就是 Hibernate 正在做的事情:它不是同时获取 和 的数据ItemData而是先获取它们的 ID,然后在n 个单独的 select 语句中获取数据。有没有办法改变这种行为?

0 投票
1 回答
268 浏览

ruby-on-rails - N+1 在与活动记录的关系中?

我有四个模型

  1. 团体
  2. 报告
  3. 评论
  4. 用户

组 => has_many => 报告

报告 => has_many => 评论

评论 => Belongs_to => 用户

当我想展示一个小组时,我会做类似的事情

在这种情况下解决 N+1 查询问题的最佳方法是什么?

0 投票
2 回答
804 浏览

nhibernate - Eager loading an optional one-to-one with NHibernate

Consider the following simplified domain:

A MovieDetail cannot exist without a Movie, but a Movie could exist without a MovieDetail (i.e. we have no details about it).

Our database has a separate table for Movie with columns Id, and a separate table for MovieDetail with columns Id and MovieId. There is also a foreign key from MovieDetail.MovieId to Movie.Id.

We've got this all mapped in NHibernate, but when getting a collection of Movie instances, we want a left outer join with MovieDetail. If not, we could have a N+1 problem when iterating over the Movie instances. That is the case now: there is a separate query for every call to the Movie.MovieDetail property.

I've tried one-to-one mapping, but that seems to be for the case when you have both instances. In our case, we don't always have a MovieDetail. Also, they don't share the same primary key.

I've researched formula's, but that would require me to make my MovieDetail implement IUserType, essentially putting NHibernate into my domain. I'd like to avoid that.

0 投票
1 回答
2809 浏览

hibernate - 注释@BatchSize 不起作用

我有 3 个 JPA 类Account,其中包括一个Address具有CityObject


我想解决 N+1 选择问题,我尝试在类上方使用 @BatchSize,但它并没有停止对数据库的 N+1 调用,因此我必须在我的persistence.xml

现在它可以工作,除了一个实体Address,所以我为 City 和 Account 获得了一个 SQL 选择,但我仍然为 Address 获得了 N 个 SQL 选择。我注意到唯一的区别是 Account 和 Address 之间的关系是一对一的

我的问题是:

  1. 一对一的关系可以成为我仍然在表地址上获得 N 选择的原因吗?为什么?
  2. 为什么注释不起作用(为什么我必须设置它persistence.xml),是否应该进行一些设置才能使注释生效?