.Net 环境下比较各种数据库插入操作的性能
1、简介
再说Windows的异步I/O操作前,先聊聊一些题外话,能帮助我们更好的理解异步I/O操作,常规的Web程序,当用户发起一次请求,当请求通过管道到达客户端的这个过程,会唤起一个线程池线程(后台线程),处理我们的业务代码,即所有的用户请求是通过异步的方式发起的,这个过程,.Net Framework会自动进行,即使我们没有显示的通过代码来实现这个过程.所以这个过程明显是存在性能瓶颈的,假设现在有一个4核服务器,意味这该服务器同时只能处理4个用户请求(超理想情况下,一般不可能),但是这个时候来了10000个用户请求(并发执行)的情况下,那么意味者大量线程会堆积起来,等待着前面的线程执行完毕,同时进行频繁的上下文切换,这个时候你会发现CPU会爆表.
上面只是一个例子,再说一个数据库的例子,现在需要向数据库插入20000条记录,分为三个版本去实现,第一个版本是单个线程同步插入,第二个版本多线程同步插入(Parallel),第三个版本多线程异步插入,来比较下性能和CPU利用零及使用情况.
(1)、单线程同步版本
这个场景是只有一个用户请求进来,进行20000次的数据库插入操作,这个版本不会产生线程堆积,因为所有的插入操作都只由主线程完成.
private static readonly string ConnectionStrings;
static Program()
{
//配置数据库连接
ConnectionStrings = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;
} static void Main(string[] args)
{ var stop = Stopwatch.StartNew();
InstertSync();
stop.Stop();
Console.WriteLine($"同步执行20000次插入操作,耗时:{stop.ElapsedMilliseconds/1000}秒");
Console.ReadKey();
} private static void InstertSync()
{
var totalCount = ;
var failCount = ; //这里以同步方式执行数据库操作,注这里只有一个线程执行所有的数据库插入操作
for (int i = ; i <= ; i++)
{
var conn = new SqlConnection(ConnectionStrings);
conn.Open();
try
{ //模拟数据库耗时操作
var sql = "insert into [dbo].[User]([Amount]) values (@Amount)";
var command = new SqlCommand(sql, conn);
command.Parameters.Add(
new SqlParameter("@Amount", i)
);
//这里线程会等待这一段时间,等待数据库返回结果,并继续执行下面的代码
var result = command.ExecuteNonQuery();
if (result == )
{
totalCount+=1;
}
else
{
failCount+=1;
} Console.WriteLine($"成功插入{totalCount}条记录,插入失败{failCount}条记录");
}
catch (Exception ex)
{ throw ex;
}
finally
{
conn.Close();
conn.Dispose();
}
}
}


再看看数据库的批请求数数据

大概稳定在300次左右每秒
(2)、多线程同步
这个场景是大多数没有使用Async Await模型的Web应用程序(Parallel代表同时有多个用户请求进来),同时数据库也使用的是同步Api,这个时候以同步的方式发起数据库请求,每个线程会等待不确定的时间,等待数据库返回结果,同时另一个线程开启,也会等待数据库返回结果,这样用户请求一多,就会产生大量的线程堆积,造成大量的内存浪费,而且当数据库开始响应线程时,线程会被唤醒,全部开始执行,这时候CPU又会开始繁忙的执行.
private static readonly string ConnectionStrings;
static Program()
{
//配置数据库连接
ConnectionStrings = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;
} static void Main(string[] args)
{
InsertAsync();
Console.ReadKey();
} private static void InsertAsync()
{
var stop = Stopwatch.StartNew();
var totalCount = ;
var failCount = ;
var res = Parallel.For(, , i =>
{
var conn = new SqlConnection(ConnectionStrings);
conn.Open();
try
{
//模拟数据库耗时操作
var sql = "insert into [dbo].[User]([Amount]) values (@Amount)";
var command = new SqlCommand(sql, conn);
command.Parameters.Add(
new SqlParameter("@Amount", i)
);
var result = command.ExecuteNonQuery();
if (result == )
{
Interlocked.Add(ref totalCount, );
}
else
{
Interlocked.Add(ref failCount, );
} Console.WriteLine($"成功插入{totalCount}条记录,插入失败{failCount}条记录");
}
catch (Exception ex)
{ throw ex;
}
finally
{
conn.Close();
conn.Dispose();
}
});
if (res.IsCompleted)
{
stop.Stop();
Console.WriteLine($"同步执行20000次插入操作,耗时:{stop.ElapsedMilliseconds / 1000}秒");
}
}


去除Interlocked稍稍快一些.明显可以发现在多线程环境下,使用同步的数据库操作api,效率显著下降.CPU的利用率也很低,同时跑了很多操作线程,但数据库使用同步Api,只能响应一个线程,其余的都需要排队.
再看看数据库批请求数

只能稳定在130次左右,说明多线程环境下,使用同步数据库操作,阻碍了请求的提交速度.个人理解.
(3)、多线程异步
这个场景用户使用基于Async Await模型的Web程序,且使用数据库的异步Api
private static readonly string ConnectionStrings;
static Program()
{
//配置数据库连接
ConnectionStrings = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;
} static void Main(string[] args)
{
InsertAsync();
Console.ReadKey();
} private static void InsertAsync()
{
var stop = Stopwatch.StartNew();
var totalCount = ;
var failCount = ;
var res = Parallel.For(, ,async i =>
{
var conn = new SqlConnection(ConnectionStrings);
conn.Open();
try
{ //模拟数据库耗时操作
var sql = "insert into [dbo].[User]([Amount]) values (@Amount)";
var command = new SqlCommand(sql, conn);
command.Parameters.Add(
new SqlParameter("@Amount", i)
); var result =await command.ExecuteNonQueryAsync();
if (result == )
{
Interlocked.Add(ref totalCount, );
}
else
{
Interlocked.Add(ref failCount, );
} Console.WriteLine($"成功插入");
}
catch (Exception ex)
{ throw ex;
}
finally
{
conn.Close();
conn.Dispose();
}
});
if (res.IsCompleted)
{
stop.Stop();
Console.WriteLine($"同步执行20000次插入操作,耗时:{stop.ElapsedMilliseconds / 1000}秒");
}
}


可以发现这个模式插入效率非常之高.但是它的插入是无序的,因为Parallel执行线程的顺序是无序的.CPU的利用率也是极高的.
再看看数据库批请求数

直线飙升>1000次的请求提交,说明使用异步Api数据库每秒接收的请求数,远大于同步方式,也是使用异步Api如此之快的原因.
.Net 环境下比较各种数据库插入操作的性能的更多相关文章
- WIN7 环境下搭建 PHP7(64 位)操作步骤
WIN7 环境下搭建 PHP7(64 位)操作步骤 一.安装与配置 Apache 1.下载 Apache下载地址:https://www.apachelounge.com/download/ 2.安装 ...
- Java CAS同步机制 原理详解(为什么并发环境下的COUNT自增操作不安全): Atomic原子类底层用的不是传统意义的锁机制,而是无锁化的CAS机制,通过CAS机制保证多线程修改一个数值的安全性。
精彩理解: https://www.jianshu.com/p/21be831e851e ; https://blog.csdn.net/heyutao007/article/details/19 ...
- 【转】编写微信聊天机器人4《聊天精灵WeChatGenius》:实时获取到微信聊天消息,hook数据库插入操作。
接上篇,使用Xposed来hook微信,找到微信进程:https://blog.csdn.net/weixin_42127613/article/details/81839537 既然已经找到了微信进 ...
- python 数据库插入操作
数据库插入操作 以下实例使用执行 SQL INSERT 语句向表 EMPLOYEE 插入记录: #!/usr/bin/python # -*- coding: UTF-8 -*- import MyS ...
- 生产环境下,MySQL大事务操作导致的回滚解决方案
如果mysql中有正在执行的大事务DML语句,此时不能直接将该进程kill,否则会引发回滚,非常消耗数据库资源和性能,生产环境下会导致重大生产事故. 如果事务操作的语句非常之多,并且没有办法等待那么久 ...
- linux下的mongodb数据库原生操作
mongodb,是一种结构最像mysql的nosql mysql中的数据库,mongodb中也有,区别在于, myql中数据库下的是表,字段和数据的形式存在 mongodb数据库下的是叫集合(和pyt ...
- Linux环境下安装MySQL数据库
Linux安装mysql服务分两种安装方法: (1).源码安装,优点是安装包比较小,只有十多M,缺点是安装依赖的库多,安装编译时间长,安装步骤复杂容易出错: (2).使用官方编译好的二进制文件安装,优 ...
- 监控Mysql主从环境下Slave延迟状态的操作记录
在MySQL主从环境下,通常会根据Seconds_Behind_Master的值来判断slave的延迟状态,这么做在大部分情况下尚可接受,但其实是并不够准确的.对于Slave延迟状态的监控,应该考虑多 ...
- Linux环境下实现对文件读写操作
---- 今天分享一下在linux系统在实现对文件读写一些基本的操作,在这之前我们要掌握一些基本的技能在Linux环境下.比如查看命令和一个函数的具体用法,就是相当于查手册,在Linux下有一个man ...
随机推荐
- p2p技术之n2n源码核心简单分析一
首先在开篇之前介绍下内网打洞原理 场景:一个服务器S1在公网上有一个IP,两个私网机器C1,C2 C1,C2分别由NAT1和NAT2连接到公网,我们需要借助S1将C1,C2建立直接的TCP连接,即由C ...
- 搭建一个webpack微服务器
[前言]:因为最近在vue2.0的时候用到了webpack的externals,才发现我之前都只是用webpack做一些搭建完项目后的“收尾工作”——即打包,而没有把它纳入到项目开发的“主体过程”中来 ...
- concurrent.futures性能阐述
python因为其全局解释器锁GIL而无法通过线程实现真正的平行计算.这个论断我们不展开,但是有个概念我们要说明,IO密集型 vs. 计算密集型. IO密集型:读取文件,读取网络套接字频繁. 计算密集 ...
- CodeForces - 939A,解题报告
题意:给出一个n个点有向图,问是否存在三个点,这三个点构成一个回路.n<=5000 模拟即可. 注意是必须三个点 多了居然不行. import java.util.*; public class ...
- JS中的instanceof和typeof,以及特殊引用类型
1.instanceof是用于测试对象类型,通常格式为:a instanceof b,返回true或falise,表示为对象a是否是类型b的实例. typeof则是用于测试基本类型,包括undefin ...
- FeatureTools
featuretools一种自动特征工程的工具.可快速生成较多类型的特征,取得不错的效果. 1.输入:把原始数据转换成featuretools的输入 2. 可以适当调整特征个数,防止训练的模型过拟合 ...
- android6.0以上权限动态申请,有视频链接可以看效果。
android6.0以上某些权限需要动态申请,虽然现在大多的手机系统版本在6.0,但是升级到6.0及以上是迟早的事,所以如何能够更好的控制动态申请权限时能有好的提示用户,及给用户带去更好的体验,是需要 ...
- mysql ERROR 1451 (23000)
问题描述:报错如下:ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint提示有外键约束, ...
- 基于IP的docker private registry 私有仓库的搭建
鉴于国内的网络环境,如果公司内部大量使用docker,镜像上传下载将是个非常耗时的工作,搭建一个私有仓库可以很好的解决自有镜像的存储,如果你在私有网络,不能使用域名的话,那么本文可以作为一个很好的例子 ...
- Astrology PHP 框架
1.Web 服务器配置 PHP 支持 URL Rewrite.PATH_INFO 2.环境需求 PHP 7.2+ 扩展:gettext 3.目录结构 + src | - autoload.php | ...