【MVC+MySQL+EntityFramework】查询性能优化笔记
通过在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能换台性能好些的服务器,应该能带来不少的提升。
【MVC+MySQL+EntityFramework】查询性能优化笔记的更多相关文章
- MySql学习—— 查询性能优化 深入理解MySql如何执行查询
本篇深入了解查询优化和服务器的内部机制,了解MySql如何执行特定查询,从中也可以知道如何更改查询执行计划,当我们深入理解MySql如何真正地执行查询,明白高效和低效的真正含义,在实际应用中就能扬长避 ...
- MySQL之查询性能优化(四)
优化特定类型的查询 COUNT()的作用 COUNT()是一个特殊函数,有两个非常不同的作用:它可以统计某个列值的数量,也可以统计行数.在统计列值时要求列值是非空的(不统计NULL). 如果在COUN ...
- MySQL之查询性能优化(三)
MySQL查询优化器的局限性 MySQL的万能“嵌套循环”并不是对每种查询都是最优的.不过还好,MySQL查询优化只对少部分查询不适用,而且我们往往可以通过改写查询让MySQL高效地完成工作. 关联子 ...
- MySQL之查询性能优化(二)
查询执行的基础 当希望MySQL能够以更高的性能运行查询时,最好的办法就是弄清楚MySQL是如何优化和执行查询的.MySQL执行一个查询的过程,根据图1-1,我们可以看到当向MySQL发送一个请求时, ...
- MySQL之查询性能优化(一)
为什么查询速度会慢 通常来说,查询的生命周期大致可以按照顺序来看:从客户端,到服务器,然后在服务器上进行解析,生成执行计划,执行,并返回结果给客户端.其中“执行”可以认为是整个生命周期中最重要的阶段, ...
- MySQL分页查询性能优化
当需要从数据库查询的表有上万条记录的时候,一次性查询所有结果会变得很慢,特别是随着数据量的增加特别明显,这时需要使用分页查询.对于数据库分页查询,也有很多种方法和优化的点.下面简单说一下我知道的一些方 ...
- sql 2008 查询性能优化笔记
索引: set statistics io on select p.productID,p.name,p.Weight,p.StandardCost from production.product p ...
- mysql笔记03 查询性能优化
查询性能优化 1. 为什么查询速度会慢? 1). 如果把查询看作是一个任务,那么它由一系列子任务组成,每个子任务都会消耗一定的时间.如果要优化查询,实际上要优化其子任务,要么消除其中一些子任务,要么减 ...
- 到底该不该使用存储过程 MySQL查询性能优化一则
到底该不该使用存储过程 看到<阿里巴巴java编码规范>有这样一条 关于这条规范,我说说我个人的看法 用不用存储过程要视所使用的数据库和业务场景而定的,不能因为阿里巴巴的技术牛逼,就视 ...
随机推荐
- Xamarin.Forms教程下载安装Windows版的Xamarin开发工具
Xamarin.Forms教程下载安装Windows版的Xamarin开发工具 下载安装Windows版的Xamarin开发工具 本节将讲解如何下载并安装Windows版的Xamarin开发工具. 下 ...
- 挑战python 之一马当先(python的广搜)
下过象棋的人都知道,马只能走'日'字形(包括旋转90°的日),现在想象一下,给你一个n行m列网格棋盘, 棋盘的左下角有一匹马,请你计算至少需要几步可以将它移动到棋盘的右上角,若无法走到,则输出-1. ...
- 通过邮箱验证注册——.net代码
在写一些面向用户的网站类的程序时,必不可少的一个就是注册,通常情况下,我们会选择邮箱验证后注册,或者手机发送验证码注册.上篇文章中已经简单的描述了手机验证注册,这篇主要介绍一下邮箱验证. 邮箱验证的步 ...
- [UOJ55]紫荆花之恋
第一次打“真正的”动态点分 如果树是静态的,直接点分:用$d_x$代表$x$到分治中心的距离,限制条件即为$d_i+d_j\leq r_i+r_j$,考虑枚举$j$,那么我们要查询有多少满足$d_i- ...
- 【bfs+优先队列】POJ2049-Finding Nemo
基本上算是普通但略有些繁琐的广搜.给出的墙面和门的坐标为点,而Nemo位于方格中. [思路] 首先思考一下如何存储下整个坐标系.我们预先约定,用一个方格的左下角顶点坐标来作为这个方格的坐标.map[i ...
- [转]为什么匿名内部类参数必须为final类型
1) 从程序设计语言的理论上:局部内部类(即:定义在方法中的内部类),由于本身就是在方法内部(可出现在形式参数定义处或者方法体处),因而访问方法中的局部变量(形式参数或局部变量)是天经地义的.是很自 ...
- Educational Codeforces Round 9 C. The Smallest String Concatenation 排序
C. The Smallest String Concatenation 题目连接: http://www.codeforces.com/contest/632/problem/C Descripti ...
- ArcGIS 10.6 安装破解教程
美国时间2018年1月17日,ArcGIS 10.6正式面向用户发布!10.6带来更完善的产品体系框架,同时全面拥抱前沿IT技术,升级平台大数据.三维.影像等核心能力,为我们打造了一个功能强大,性 ...
- windows2012 IIS部署GeoTrust证书踩过的坑。
系统:windows2012 环境:IIS8 在阿里云上买了GeoTrust证书, 按照说明下载证书到服务器, 导入证书, 给IIS站点部署https. 阿里云部署帮助文档:https://help ...
- 二十四种设计模式:桥接模式(Bridge Pattern)
桥接模式(Bridge Pattern) 介绍将抽象部分与它的实现部分分离,使它们都可以独立地变化. 示例有一个Message实体类,对它的操作有Insert()和Get()方法,现在使这些操作的抽象 ...