通过在DbContext中定了表之间的关系,查询后在View中通过item.ProjectOverHour来显示关联表数据。

            modelBuilder.Entity<ProjectOverHour>()
.HasMany(e => e.DailyReports)
.WithRequired(e => e.ProjectOverHour)
.HasForeignKey(e => new { e.ProjectIndex, e.EmployeeId, e.ReportDate })
.WillCascadeOnDelete(false);

开发完后发现页面仅仅显示10条记录耗时已经超过1s了。

调查后发现如下原因:

1、EntityFramework中,关联表数据不是在查询时加载的,而是在用到时(即View中调用item.ProjectOverHour时)才会去DB查询。

将画面显示条数改为20条后,页面加载时间成正比例上升。

考虑不让EntityFramework执行多次查询,使用Select方法使其一次查询出所需要的关联数据。

Select<DailyReport, DailyReportSearchResultViewModel>(d => new DailyReportSearchResultViewModel()
{
...
OverHour = d.ProjectOverHour.OverHour,
...
});

这样修改后生成的SQL中关联了需要的表,并且只执行了一次查询。

因为在DbContext中定义的是外键关系,导致生成的SQL文是InnerJoin的关系,而不是想定的LeftJoin关系。

调查后没有发现如何在DbContext中定义Left Join关系。(有WithOptional方法,但执行时总是出错)

后来改用如下写法,实现了Left Join的效果,查询结果也是正确的。

from d in dailyReportsQuery
join ot1 in db.ProjectOverHours
on new { ProjectIndex = d.ProjectIndex, EmployeeId = d.EmployeeId, ReportDate = d.ReportDate }
equals new { ProjectIndex = ot1.ProjectIndex, EmployeeId = ot1.EmployeeId, ReportDate = ot1.WorkDate } into ottemp
from ot in ottemp.DefaultIfEmpty()
select new DailyReportSearchResultViewModel
{
...
ApprovalOverHour = ot.ApprovalOverHour,
...
};

但是页面加载时间仍然很长(4s左右)。

后来发现把关联表中的两个View的算法改为Template后,数据查询快了很多。

这个感觉很没道理,查询应该Meger查询更快才对。

在用生成的SQL测试时,发现创建索引占据了99%的时间。

原来关联View的业务主键,在原来的表里并不是主键。

将原来的表里追加相应的索引后,查询快了很多。

逐个把关联的表都加了索引。

上述修改后,数据少时页面加载页很快(0.1s左右)。

但是在追加了2w条数据后再测试时,发现页面加载又变慢了。

还是EntityFramework生成的SQL文的问题。

因为使用OrderBy来排序,并且使用了分页,生成的SQL文变成了如下的形式。

SELECT
...
FROM (SELECT
...
FROM `dailyreport` AS `Extent1`
LEFT OUTER JOIN ...
INNER JOIN ...
WHERE (0 = `Extent1`.`DeleteFlag`) ... ) AS `Project1`
ORDER BY
`Project1`.`...` DESC,
`Project1`.`...` ASC,
`Project1`.`...` DESC
LIMIT 0,10

把查询结果作为子查询,然后再排序和分页。

查询用时1.1s,其中Sending data占了99%的时间。

仍然比最初的页面加载时间要多。

最后改为将InnerJoin的表用Select方法取出相关数据,LeftJoin的表的数据,通过循环Select结果集,单独取得这些数据。

修改后开发环境页面加载时间在0.2~0.3s,服务器环境在0.4~0.5s。

虽然不是很理想,但是对于社内用的小系统来说,性能已经可以接受了。

2、MySql的DB服务器是放在一台虚拟机上的,性能一直不好,并且已经有别的系统在用。

因为要用到该DB服务器上的另一个数据库的数据,所以考虑把本系统的数据建立在一台新机器上,然后建立远程连接表来取数据。

但发现每次查询都要从远程服务器取得所有的数据然后再查询,效率极差。

最后还是只好放在该服务器上了。

CREATE TABLE IF NOT EXISTS `tablename`` (
......
) ENGINE=FEDERATED DEFAULT CHARSET=utf8
CONNECTION='mysql://user:password@server:3306/schema/tablename';

如果DB能换台性能好些的服务器,应该能带来不少的提升。

已添加到【MVC5】ASP.NET MVC 项目笔记汇总

【MVC+MySQL+EntityFramework】查询性能优化笔记的更多相关文章

  1. MySql学习—— 查询性能优化 深入理解MySql如何执行查询

    本篇深入了解查询优化和服务器的内部机制,了解MySql如何执行特定查询,从中也可以知道如何更改查询执行计划,当我们深入理解MySql如何真正地执行查询,明白高效和低效的真正含义,在实际应用中就能扬长避 ...

  2. MySQL之查询性能优化(四)

    优化特定类型的查询 COUNT()的作用 COUNT()是一个特殊函数,有两个非常不同的作用:它可以统计某个列值的数量,也可以统计行数.在统计列值时要求列值是非空的(不统计NULL). 如果在COUN ...

  3. MySQL之查询性能优化(三)

    MySQL查询优化器的局限性 MySQL的万能“嵌套循环”并不是对每种查询都是最优的.不过还好,MySQL查询优化只对少部分查询不适用,而且我们往往可以通过改写查询让MySQL高效地完成工作. 关联子 ...

  4. MySQL之查询性能优化(二)

    查询执行的基础 当希望MySQL能够以更高的性能运行查询时,最好的办法就是弄清楚MySQL是如何优化和执行查询的.MySQL执行一个查询的过程,根据图1-1,我们可以看到当向MySQL发送一个请求时, ...

  5. MySQL之查询性能优化(一)

    为什么查询速度会慢 通常来说,查询的生命周期大致可以按照顺序来看:从客户端,到服务器,然后在服务器上进行解析,生成执行计划,执行,并返回结果给客户端.其中“执行”可以认为是整个生命周期中最重要的阶段, ...

  6. MySQL分页查询性能优化

    当需要从数据库查询的表有上万条记录的时候,一次性查询所有结果会变得很慢,特别是随着数据量的增加特别明显,这时需要使用分页查询.对于数据库分页查询,也有很多种方法和优化的点.下面简单说一下我知道的一些方 ...

  7. sql 2008 查询性能优化笔记

    索引: set statistics io on select p.productID,p.name,p.Weight,p.StandardCost from production.product p ...

  8. mysql笔记03 查询性能优化

    查询性能优化 1. 为什么查询速度会慢? 1). 如果把查询看作是一个任务,那么它由一系列子任务组成,每个子任务都会消耗一定的时间.如果要优化查询,实际上要优化其子任务,要么消除其中一些子任务,要么减 ...

  9. 到底该不该使用存储过程 MySQL查询性能优化一则

    到底该不该使用存储过程   看到<阿里巴巴java编码规范>有这样一条 关于这条规范,我说说我个人的看法 用不用存储过程要视所使用的数据库和业务场景而定的,不能因为阿里巴巴的技术牛逼,就视 ...

随机推荐

  1. Java HashSet的元素内容变化导致的问题

    概述 HashSet元素引用的对象的内容发生变化,会导致"元素不属于集合"的问题.事实上这个元素还在集合里,但是调用contains方法进行判断,得到的结果却是false. 正文 ...

  2. 【BZOJ 2151】 2151: 种树 (贪心+堆+双向链表)

    2151: 种树 Description A城市有一个巨大的圆形广场,为了绿化环境和净化空气,市政府决定沿圆形广场外圈种一圈树.园林部门得到指令后,初步规划出n个种树的位置,顺时针编号1到n.并且每个 ...

  3. VB查询数据库之组合查询——机房收费总结(二)

    在机房收费系统中,组合查询用的还是挺多的,像上机状态查询窗体.学生上机统计信息窗体.操作员工记录窗体.基本信息维护窗体.这其中,学生基本信息维护窗体中的东西比较多,就以它为例子,说说组合查询吧! 学生 ...

  4. bzoj 1783: [Usaco2010 Jan]Taking Turns

    1783: [Usaco2010 Jan]Taking Turns Description Farmer John has invented a new way of feeding his cows ...

  5. 零起点学算法08——简单的输入和计算(a+b)

    #include <stdio.h> int main() { int a; int b; scanf("%d %d",&a,&b); printf(& ...

  6. Codeforces Round #345 (Div. 2) B. Beautiful Paintings 暴力

    B. Beautiful Paintings 题目连接: http://www.codeforces.com/contest/651/problem/B Description There are n ...

  7. Xcode 6.4项目中的常见文件(info.plist)

    Xcode 6.4项目中的常见文件(info.plist) 代码中获取 info.plist[NSBundle mainBundle] infoDictionary]; Bundle display ...

  8. Android——多线程之Handler

    Why? 因为在Android系统中UI操作并不是线程安全的,如果多个线程并发的去操作同一个组件,可能导致线程安全问题.为了解决这一个问题, android制定了一条规则:只允许UI线程来修改UI组件 ...

  9. .Net中的7Zip——Sharpcompress

    虽然微软在.net 4.5中集成了对zip的解压支持,但还是比较弱.如果我们想让程序像7zip那样支持万能解压,Sharpcompress可以帮你实现这个目标,它是一个C#写的压缩/解压工具,虽然还没 ...

  10. HDU 4417 Super Mario(划分树)

    Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...