【问题标题】:Mysql - Entity Framework performance issue on "order by" / SubqueryMysql - “order by”/子查询的实体框架性能问题
【发布时间】:2012-06-26 00:06:13
【问题描述】:

我有一张存储 3k 条记录的表,

我是 Entity Framework 和 ORM 的新手,但我可以理解出现问题。

当我运行这个 linq 查询时:

repo.GetQuery<Article>().Where(foo=>foo.Expires_date>=date
                            && foo.Istoparticle==true
                            && foo.Isfrontpage==false)
                        .OrderByDescending(foo=>foo.Date)
                        .Take(4);

我在 mysql 端得到这个查询:

选择 `Project1`.`Id`, `Project1`.`User_id`, `Project1`.`Category_id`, `Project1`.`标题`, `Project1`.`值`, `Project1`.`关键字`, `Project1`.`描述`, `Project1`.`图片`, `Project1`.`投票`, `Project1`.`Views`, `Project1`.`Isvisible`, `Project1`.`Isfrontpage`, `Project1`.`Istoparticle`, `Project1`.`日期`, `Project1`.`Expires_date`, `Project1`.`Votes_sum` 从(选择 `Extent1`.`Id`, `Extent1`.`User_id`, `Extent1`.`Category_id`, `Extent1`.`标题`, `Extent1`.`值`, `Extent1`.`关键字`, `Extent1`.`描述`, `Extent1`.`图片`, `Extent1`.`投票`, `Extent1`.`Votes_sum`, `Extent1`.`Views`, `Extent1`.`Isvisible`, `Extent1`.`Isfrontpage`, `Extent1`.`Istoparticle`, `Extent1`.`Expires_date`, `Extent1`.`日期` FROM `tcms_articles` AS `Extent1` WHERE `Extent1`.`Expires_date` >= '2012-06-24 13:41:47.816') AS `Project1` 订购方式 `Project1`.`Date` DESC LIMIT 4

执行此查询大约需要 3.50 秒。

这个查询的解释:

+----+-------------+------------+-------+--------- ------+--------------+----------+------+------+---- ------------+ |编号 |选择类型 |表|类型 |可能的键 |关键 | key_len |参考 |行 |额外 | +----+-------------+------------+-------+--------- ------+--------------+----------+------+------+---- ------------+ | 1 |初级 | |全部 |空 |空 |空 |空 | 4054 |使用文件排序 | | 2 |派生 |范围1 |范围 |过期日期 |过期日期 | 8 |空 | 4053 |使用位置 | +----+-------------+------------+-------+--------- ------+--------------+----------+------+------+---- ------------+

当我查询时:

SELECT *
    FROM tcms_articles
    WHERE expires_date >= '2012-06-24 13:41:47.816'
    ORDER BY date DESC
    limit 4

我得到 0.01 秒...

再次运行解释我得到:

+----+-------------+---------------+-------+------ ------+------+---------+------+------+------ ----+ |编号 |选择类型 |表|类型 |可能的键 |关键 | key_len |参考 |行 |额外 | +----+-------------+---------------+-------+------ ------+------+---------+------+------+------ ----+ | 1 |简单 | tcms_articles |索引 |过期日期 |日期 | 8 |空 | 11 |使用位置 | +----+-------------+---------------+-------+------ ------+------+---------+------+------+------ ----+

我不明白为什么会这样。

实体框架 4.3 MySQL 连接器网络 6.5.4.0

编辑:

tcms_articles:

创建表`tcms_articles`( `Id` int(10) unsigned NOT NULL AUTO_INCREMENT, `User_id` int(10) 无符号 DEFAULT NULL, `Category_id` int(10) 无符号 DEFAULT NULL, `标题` varchar(255) 默认为空, `值`长文本, `Keywords` varchar(255) NOT NULL DEFAULT '', `Description` varchar(255) NOT NULL DEFAULT '', `图片`长文本不为空, `Votes` int(10) unsigned NOT NULL DEFAULT '1', `Votes_sum` int(10) unsigned NOT NULL DEFAULT '5', `Views` int(10) unsigned NOT NULL DEFAULT '0', `Isvisible` tinyint(1) unsigned NOT NULL DEFAULT '1', `Isfrontpage` tinyint(1) unsigned NOT NULL DEFAULT '0', `Istoparticle` tinyint(1) unsigned NOT NULL DEFAULT '1', `Expires_date` datetime NOT NULL DEFAULT '2099-12-31 00:00:00', `日期`日期时间不为空, 主键(`Id`), KEY `article_users` (`User_id`) 使用 BTREE, KEY `article_section` (`Category_id`) 使用 BTREE, KEY `Isvisible_index2` (`Isvisible`) 使用 BTREE, KEY `Istoparticle_index2` (`Istoparticle`) 使用 BTREE, KEY `Expires_date_index2` (`Expires_date`) 使用 BTREE, KEY `isfrontpage2` (`Isfrontpage`) 使用 BTREE, KEY `Date_index2` (`Date`) 使用 BTREE, 约束 `tcms_articles_ibfk_1` 外键 (`Category_id`) 参考 `tcms_categories` (`Id`) 在更新级联上删除级联, 约束 `tcms_articles_ibfk_2` 外键 (`User_id`) 参考 `tcms_users` (`Id`) ON DELETE CASCADE ON UPDATE CASCADE ) 引擎=InnoDB AUTO_INCREMENT=80 默认字符集=utf8;

那么为什么 Linq 会产生这个查询,我该如何/可以解决这个问题?

【问题讨论】:

  • 你在问什么?为什么 linq 会产生错误的查询?
  • 我看到的问题是子查询。有没有其他的写法或者是提供者(MySql Connector)的问题?
  • 任何人都可以看到为什么这个愚蠢的子查询在那里开始?查看 LINQ 语句,我认为没有理由开始使用它。
  • 我认为这是由于匿名类型(foo)的投影原因,但 LINQ 期望服务器(MsSql、Mysql 等)优化查询。但这在 MySql 中没有发生:/
  • 又一个第三者惹麻烦的例子?

标签: c# mysql performance entity-framework


【解决方案1】:
repo.GetQuery<Article>().Where(foo=>foo.Expires_date>=date  -- Note 1
                        && foo.Istoparticle==true
                        && foo.Isfrontpage==false)
                    .OrderByDescending(foo=>foo.Date)       -- Note 2
                    .Take(4);

在两个地方都使用foo.Expires_date

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-09
    • 1970-01-01
    • 2016-03-10
    • 1970-01-01
    • 2010-11-06
    • 2014-07-17
    相关资源
    最近更新 更多