【问题标题】:Explain MySQL Join Performance解释 MySQL 连接性能
【发布时间】:2020-09-12 19:25:30
【问题描述】:

我有一些 mySQL 表,它们反映了 BlogPost、User 之间的关系以及 User 和 BlogPost 之间的交互

我编写了一些查询来获取用户尚未交互的所有帖子。此查询是从 EntityFramework 生成的

_dbContext.Post.Where(!p.UserPostInteractions.Any(u => u.User.IndexedProperty == "SomeSpecificString")

SQL

SELECT COUNT(*)
      FROM `Post` AS `p`
      WHERE ( NOT EXISTS (
          SELECT 1
          FROM `UserPostInteractions` AS `u`
          LEFT JOIN `Users` AS `u.User` ON `u`.`UserId` = `u.User`.`Id`
          WHERE (`u.User`.`IndexedPropertyOnUserTable` = 'SomeSpecificString') AND (`p`.`Id` = `u`.`PostId`)) )

此查询运行 3.8 秒。说明表如下

+---+--------------------+--------+-------+---------------------------------------------------------------+--------------------------------+-----+-------------------+------+--------------------------+
| 1 | PRIMARY            | p      | index |                                                               | IX_Post_ParentPostId           |   5 |                   | 7261 | Using where; Using index |
| 2 | DEPENDENT SUBQUERY | u.User | ref   | PRIMARY,IX_Users_IndexedProperty                              | IX_Users_IndexedProperty       | 383 | const             |    1 | Using where; Using index |
| 2 | DEPENDENT SUBQUERY | u      | ref   | IX_UserPostInteractions_PostId,IX_UserPostInteractions_UserId | IX_UserPostInteractions_UserId |   5 | db-name.u.User.Id |   17 | Using where              |
+---+--------------------+--------+-------+---------------------------------------------------------------+--------------------------------+-----+-------------------+------+--------------------------+

我尝试将其修改为

SELECT COUNT(*)
      FROM `Post` AS `p`
      WHERE ( NOT EXISTS (
          SELECT 1
          FROM `UserPostInteractions` AS `u`
          LEFT JOIN `Users` AS `u.User` ON `u`.`UserId` = `u.User`.`Id`
          WHERE (`u.User`.`Id` = 'usingIdInstead') AND (`p`.`Id` = `u`.`PostId`)) )

此查询运行 0.6 秒

这有什么不正常的吗?我可以做些什么来提高这个查询的性能?

【问题讨论】:

  • 您的别名明显异常,您的 LEFT JOIN 呈现为 INNER JOIN(可以通过执行 EXPLAIN EXTENDED 后跟 SHOW WARNINGS 来证明)。你也没有错过 p 和子查询之间的一些相关性吗!?!

标签: mysql entity-framework entity-framework-core


【解决方案1】:

这是同一件事的另一种说法:

SELECT COUNT(*)
  FROM post p
  LEFT
  JOIN (
      SELECT up.postid
      FROM userpostinteractions up
      JOIN users u
      ON up.userid = u.id
      WHERE u.indexedpropertyonusertable = 'SomeSpecificString' 
    ) x
      ON p.id = x.postid
WHERE x.postid IS NULL

【讨论】:

  • 此查询给出正确的数据并在不到 100 毫秒内返回。你能解释为什么问题中提供的速度很慢吗?我想知道为什么 EntityFramework 选择生成像第一个这样可怕的查询
  • Quassnoi 对 NOT EXISTS 的(看似违反直觉的)问题进行了冗长的解释——尽管这一切都让我有点不知所措)explainextended.com/2009/09/15/…
  • 这是 MySQL explainextended.com/2009/09/18/…的链接
猜你喜欢
  • 2012-07-01
  • 2016-09-11
  • 2018-05-09
  • 2015-07-29
  • 1970-01-01
  • 1970-01-01
  • 2013-05-15
  • 1970-01-01
  • 2013-07-06
相关资源
最近更新 更多