【问题标题】:How to optimize this LINQ to EF/Sql query (many to many to many relationship)?如何优化此 LINQ to EF/Sql 查询(多对多关系)?
【发布时间】:2013-03-17 17:43:38
【问题描述】:

我正在实现一个权限系统,其中用户位于角色中,然后该角色具有权限,我正在考虑查询它们的最快方法:

目前我有以下 LINQ 查询:

var grant = db.Permissions.Any(p => p.Group == group && p.PermissionKey == permission
&& !p.Roles.Any(r => !r.IsAllowed && r.Role.Users.Any(u => u.UserName == user.Identity.Name)) 
&& p.Roles.Any(r => r.IsAllowed && r.Role.Users.Any(u => u.UserName == user.Identity.Name)));

return grant;

在 EF 缓存实体后大约需要 1-2 毫秒(第一次需要 15-20 毫秒)。这不是很慢,但可以查询很多(例如,如果允许用户查看该项目,菜单系统会检查每个项目)我问是否有更快的可能?

目前我唯一能想到的就是创建一个用户权限缓存以在第一次调用后完全摆脱查询,但缓存对我来说始终是最后的手段(尤其是当你 nned如果权限发生变化,请考虑清除它。)。

更新:按照 Marcin 的建议使用 Any,但速度并不快...

更新 2:我将 IsAllowed 移动到映射表并调整查询以仅使用一个...

【问题讨论】:

  • 你不能对多个项目进行查询,并将结果缓存相当短的时间,比如 30 秒吗?这样您就可以获得相当准确的结果,并具有单一查询的优势。
  • @Maarten:“查询多个项目”是什么意思?那是为了我的“菜单示例”吗?
  • @chrfin 同时检查多个(全部)所需的权限 - 使用以数据库为中心的连接 - 将减少查询。但我只使用 LINQ2SQL,所以我不知道 EF 缓存如何适应 ..
  • 您的表格有多少条目?几个月后他们会有多少?如果这些查询经常运行,我肯定会使用一些缓存。即使是 1 秒的高速缓存锁存时间也会显着提高性能。那么一个不在同一台机器上运行的数据库呢?也许笛卡尔积会在这里为您提供帮助。你试过join吗?
  • AND:您运行了两次几乎相同的查询,只是更改了IsAllowed:查询IsAllowed 的值怎么样?

标签: c# sql linq entity-framework


【解决方案1】:

您应该将每个Count() > 0 语句更改为Any 方法调用,例如:

r => r.Users
      .Count(u => u.UserName == user.Identity.Name) > 0

应替换为:

r => r.Users
      .Any(u => u.UserName == user.Identity.Name)

【讨论】:

  • 感谢您的提示 - 看起来好多了,但不会影响性能(我猜 EF 会从中创建相同的查询)。
  • +1 代码的意图更具可读性。惊讶于性能是一样的。也许 EF 有一个优化器,可以以相同的方式解释这两个 LINQ to EF 查询?
  • 不管 EF 是否将 Count() > 0 优化为 Any(),我想 SQL Query Planner 将两者视为相同(即 COUNT(x) > 0),如果它通过这种方式..跨度>
  • 我会接受您的解决方案,因为它对我帮助最大。现在我坚持使用这个和 1s 缓存...
【解决方案2】:

您是否尝试过在数据库中创建索引视图?

CREATE VIEW mySchema.UserRolePermission
WITH SCHEMABINDING
/* your SELECT goes here */
GO
CREATE UNIQUE CLUSTERED INDEX MyIndexName
ON mySchema.UserRolePermission (UserName, PermissionKey);
GO

然后,您的 LINQ2SQL 查询将改为从此视图中直接选择。它可能会更快,因为 SQL Server 将在您用于搜索的 UserName 和 PermissionKey 字段上创建索引。由于这是一个权限系统,我假设您不会经常插入这些表(索引视图可能会减慢插入速度),但您会更频繁地读取这些表。

由于 EF 缓存,您第二次触发此查询也可能不会更快,但可能是因为 SQL 服务器缓存。不确定,但可能值得一试。

【讨论】:

  • 感谢您的输入,但数据库不是“问题”,因为 EF 缓存了所有实体,所以它更多的是“如何更好地查询对象模型”...
猜你喜欢
  • 1970-01-01
  • 2014-07-13
  • 1970-01-01
  • 2013-06-27
  • 1970-01-01
  • 1970-01-01
  • 2021-10-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多