C#+EF+SqlServer性能优化笔记

server/2025/3/18 23:31:38/

文章目录

  • 前言
  • 一、C#EF 代码优化
    • 1.接口代码改异步
    • 2.查询异步,只查询需要的数据
    • 3.查询数据判断时
    • 4.直接使用sql查询
  • 二、数据库优化
    • 1.减少关联表,一些基础数据,字典表可以考虑放到redis中,在代码中映射
    • 2.增加索引,删除无效索引,查看索引碎片率,重建索引
    • 3.更深层可以参考这篇文章:


前言

数据库和服务器降配之后,系统开始了各种超时,查询超时,保存超时,本身系统逻辑也很复杂,开发了五六年了,各种shi代码,慢sql,以下是一些经验的记录,便于以后忘了可以看看,也希望能帮到你!


一、C#EF 代码优化

1.接口代码改异步

代码(示例):

[ResponseType(typeof(object)), Route("api/OpenApi/AddDataApi"), HttpPost]
public async Task<IHttpActionResult> AddDataApi(RuqestModel model)
{if(model == null){return BadRequest();}var res = await AddDataAsync(model);//增加await,调用异步方法return OK(res);
}private async Task<int> AddDataAsync(DbContext db, Tables model, long currentId)
{db.Tables.Add(model);await db.SaveChangesAsync();//增加await,调用异步保存方法return 1;
}

2.查询异步,只查询需要的数据

代码(示例):

//1、异步方法可以提示效率
//2、通过select方法只查询Value字段,在大数据量的情况下,减少了传输的数据,可以提示效率
var Config = await db.MdmConfigs.Where(x => x.IsDeleted == false && x.Code == "Code1").Select(x => new { x.Value }).FirstOrDefaultAsync();

3.查询数据判断时

代码(示例):

//1、判断数据是否存在时
var Config = await db.MdmConfigs.Where(x => x.IsDeleted == false && x.Code == "Code1").FirstOrDefaultAsync();if(Config == null)
{return BadRequest();
}
//可以优化为:
var IsExist= await db.MdmConfigs.AnyAsync(x => x.IsDeleted == false && x.Code == "Code1");if(!IsExist)
{return BadRequest();
}

4.直接使用sql查询

代码(示例):

//复杂查询可以直接使用sql查询,下面的sql是简写
var config = db.Database.SqlQuery<MdmConfig>("SELECT * FROM MdmConfig WHERE IsDeleted = 0 and Code = 'Code1'").FirstOrDefault();

二、数据库优化

1.减少关联表,一些基础数据,字典表可以考虑放到redis中,在代码中映射

2.增加索引,删除无效索引,查看索引碎片率,重建索引

代码(示例):


--查看表索引详情
EXEC sp_helpindex 'YourSchema.YourTableName';--查看数据库缺失索引
USE DbName
GO
SELECT mid.statement AS TableName,mid.equality_columns AS EqualityColumns,mid.inequality_columns AS InequalityColumns,mid.included_columns AS IncludedColumns,migs.user_seeks AS UserSeeks,migs.user_scans AS UserScans,migs.avg_user_impact AS AvgUserImpact,migs.avg_total_user_cost AS AvgTotalUserCost,'CREATE INDEX IX_' + OBJECT_NAME(mid.OBJECT_ID) + '_' + CAST(mid.index_handle AS VARCHAR(10)) + ' ON ' + mid.statement + ' (' + ISNULL(mid.equality_columns, '') + CASE WHEN mid.equality_columns IS NOT NULL AND mid.inequality_columns IS NOT NULL THEN ',' ELSE '' END + ISNULL(mid.inequality_columns, '') + ')' + ISNULL(' INCLUDE (' + mid.included_columns + ')', '') AS CreateIndexStatement
FROM sys.dm_db_missing_index_details AS mid
JOIN sys.dm_db_missing_index_groups AS mig ON mid.index_handle = mig.index_handle
JOIN sys.dm_db_missing_index_group_stats AS migs ON mig.index_group_handle = migs.group_handle
WHERE mid. statement  LIKE '%DbName%' -- 确保只针对当前数据库运行
ORDER BY migs.avg_user_impact DESC;--查看数据库无效索引
SELECTind.index_id,obj.name AS TableName,ind.name AS IndexName,ind.type_desc,indUsage.user_seeks,indUsage.user_scans,indUsage.user_lookups,indUsage.user_updates,indUsage.last_system_seek,indUsage.last_user_scan,'drop index [' + ind.name + '] ON [' + obj.name + ']' AS DropIndexCommand
FROMsys.indexes AS ind
INNER JOIN sys.objects AS obj ON ind.object_id = obj.object_id
LEFT JOIN sys.dm_db_index_usage_stats indUsage ON ind.object_id = indUsage.object_id
AND ind.index_id = indUsage.index_id
WHEREind.type_desc <> 'HEAP'
AND obj.type <> 'S'
AND OBJECTPROPERTY(obj.object_id,'isusertable'
) = 1
AND (ISNULL(indUsage.user_seeks, 0) = 0AND ISNULL(indUsage.user_scans, 0) = 0AND ISNULL(indUsage.user_lookups, 0) = 0
)
ORDER BYobj.name,ind.name------------查看索引碎片率并大于30%
SELECT OBJECT_NAME(ind.OBJECT_ID) AS TableName,ind.name AS IndexName,indexstats.index_type_desc AS IndexType,indexstats.avg_fragmentation_in_percent 
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, NULL) indexstats INNER JOIN sys.indexes ind ON ind.object_id = indexstats.object_id AND ind.index_id = indexstats.index_id 
WHERE indexstats.avg_fragmentation_in_percent >30 ------------碎片率
ORDER BY indexstats.avg_fragmentation_in_percent DESC--重新组织索引(把第1步里的表名TableName复制进来,并调整阈值)
ALTER INDEX ALL ON [TableName] 
REBUILD WITH (FILLFACTOR = 90, SORT_IN_TEMPDB = ON,STATISTICS_NORECOMPUTE = ON); --查看索引碎片率并大于30%并进行整理
DECLARE @SQL NVARCHAR(MAX) = N'';SELECT @SQL += 'ALTER INDEX [' + ind.name + '] ON [' + OBJECT_NAME(ind.OBJECT_ID) + '] REBUILD WITH (ONLINE=ON, FILLFACTOR=90);' + CHAR(13)
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, NULL) AS indexstats
INNER JOIN sys.indexes AS ind ON ind.object_id = indexstats.object_id AND ind.index_id = indexstats.index_id
WHERE indexstats.avg_fragmentation_in_percent > 30AND ind.name IS NOT NULL;PRINT @SQL;
-- 如果需要执行,取消以下注释
-- EXEC sp_executesql @SQL;

3.更深层可以参考这篇文章:

数据库优化 ——关于tempdb系统库影响IO和数据库性能的一些问题


http://www.ppmy.cn/server/176079.html

相关文章

PosterRender 实现微信下程序 分享商品生成海报

PosterRender 是什么 PosterRender 是一种专注于生成高质量海报图像的技术或工具&#xff0c;常用于生成静态图片&#xff0c;特别是适合用于营销、宣传和展示的图形设计。它通常用于在服务端或客户端渲染复杂的图像&#xff0c;包括文字、图形、图标、背景等&#xff0c;生成…

stm32week7

stm32学习 三.通信 10.BKP和RTC BKP(backup registers)备份寄存器 BKP可以存储数据&#xff0c;掉电丢失&#xff0c;平时用外部电源供电&#xff0c;外部电源切断后用VBAT维持供电&#xff0c;当系统在待机状态下被唤醒&#xff0c;或系统复位或电源复位时&#xff0c;它们…

C++ STL list

文章目录 1. std::list 的特性2. 包含头文件3. 声明和初始化 std::list4. 常用成员函数4.1 元素访问4.2 容量4.3 修改容器4.4 迭代器4.5 其他常用函数 5. 使用示例6. 注意事项7. 与其他容器的比较总结 在 C 标准模板库&#xff08;STL&#xff09;中&#xff0c;std::list 是一…

qt介绍图表 charts 一

qt chartsj基于Q的Graphics View框架&#xff0c;其核心组件是QChartView和QChart.QChartView是一个显示图表的独立部件&#xff0c;基类为QGraphicsView.QChar类管理图表的序列&#xff0c;图例和轴示意图。 绘制一个cos和sin曲线图&#xff0c;效果如下 实现代码 #include…

单臂路由+VLANIF

涉及的具体实验步骤在&#xff1a;三层交换机实现路由功能_三层交换机打开路由功能-CSDN博客 1.技术背景&#xff1a;VLAN间通信 传统交换二层组网中&#xff0c;默认所有网络都处于同一个广播域&#xff0c;这带了诸多问题。VLAN&#xff08;Virtual Local Area Network&…

浅谈StarRocks数据库简介及应用

StarRocks是一款高性能的实时分析型数据库&#xff0c;专为复杂的SQL查询提供极高的性能&#xff0c;尤其适用于数据分析场景。它是一款开源的新一代极速全场景MPP&#xff08;Massively Parallel Processing&#xff0c;大规模并行处理&#xff09;数据库&#xff0c;致力于构…

3ds Max 导入到 After Effects 还原摄像机要注意事项--deepseek

我&#xff1a;dp我这有两个脚本分别是syn软件相机导出到max的和syn软件相机导出到ae的&#xff0c;你能看出差别来吗&#xff1f;如果我想把max里的相机导入到ae里&#xff0c;保持原来的位置方向&#xff0c;该怎么做 dp&#xff1a;从这两个脚本可以看出&#xff0c;3ds Ma…

set详讲(C++)

目录 1. 前言 2. 预备知识 2.1 关联式容器 2.2 键值对 3. set详解 3.1 set是什么 3.2 set模板参数列表 3.3 set构造 3.4 set的使用 3.4.1 insert 3.4.2 find 3.4.3 erase 3.4.4 swap 3.4.5 empty 3.4.6 size 3.4.7 count 3.4.8 lower_bound 3.8.9 upper_bound…