性能优化知识(不定期更新)

SqlServer优化

sqlserver Not in 优化

not in 优化

当需要过滤的数据比较少时用not in
当需要过滤的数据比较多时用not exists
比如你查询一张表,表里的数据只有几百条或者几千条就可以选择用not in
如果表里的数据量上万了那就选择用 not exists

not in 用法

select * from tablename where id not in (''''')

not exists 用法

select * from tablename where id not exists (.....)

sqlserver格式化表

TRUNCATE  TABLE  TbName   --TbName是表名

ORM框架的选择

SqlSugar

SqlSugar是国人开发者开发的一款基于.NET的ORM框架,是可以运行在.NET 4.+ & .NET CORE的高性能、轻量级 ORM框架,众多.NET框架中最容易使用的数据库访问技术。
具有超越Dapper的性能 ,走的是EMIT结构中间语言动态编译到程序集,完成高性能的实体绑定,达到原生水平
特点:

  • 开源、免费
  • 国内开发者开发、维护;
  • 支持.NET Core;
  • 支持主流数据库,如:SQL Server,MySql,Oracle,Sqlite等;
  • 维护更新及时

这里有它的详细介绍:传送门

PetaPoco

PetaPoco是一款适用于.NET应用程序的轻型对象关系映射器(ORM, Object Relational Mapper)。与那些功能完备的ORM(如NHibernate或Entity Framework)不同的是,PetaPoco更注重易用性和性能,而非丰富的功能。使用PetaPoco只需要引入一个C#文件,可以使用强类型的 POCO(Plain Old CLR Object),并支持使用T4模板生成的类等等 性能不如dapper,但仅次于他

特点:

  • 开源、免费
  • 可与SQL Server、SQL Server CE、MySQL、PostgreSQL以及Oracle数据库协同工作。
  • 包含针对Insert/Delete/Update/Save以及IsNew的多个辅助方法。
  • 支持简单事务
  • 对于翻页请求会自动计算总记录数,并获取特定分页。
  • 支持参数替换,能够从对象属性中抓取命名参数(named parameters)
  • 包括一个消耗资源很少的SQL Builder类
  • 部分记录更新
  • 包括T4 Templates,可以用于基于数据库结构生成POCO类。

linq2db

linq2db也是一款快速、轻量、类型安全的POCO对象和数据库映射的ORM框架。从构架上来说,linq2db是对比如:Dapper、PetaPoco这个的微ORM的进一步封装,但它不像Entity Framework那样笨重。它没有实现状态跟踪,需要自己处理实体的状态更改等。

EF

ADO.NET Entity Framework 是微软以 ADO.NET 为基础所发展出来的对象关系对应 (O/R Mapping) 解决方案。该框架曾经为.NET Framework的一部分,但version 6之后从.NET Framework分离出来。
适合处理大数据。在查询需要多表查询可以选择它,但是它比较笨重。

NHibernate

NHibernate是一个面向.NET环境的对象/关系数据库映射工具。对象/关系数据库映射(object/relational mapping,ORM)这个术语表示一种技术,用来把对象模型表示的对象映射到基于SQL的关系模型数据结构中去。
特点:

  • 开源、免费
  • 批量写入
  • 批量读/多重查询特性(我理解是在说Future?)
  • 批量的集合加载
  • 带有lazy="extra"的集合
  • 集合过滤器和分页集合
  • 二级缓存(实际上NH的二级缓存貌似也很简单?)
  • 集成和扩展性
  • 代码自动生成,减少代码和sql的开发量,使开发人员摆脱开sql,ado.net和事务,缓存等底层

Dapper

Dapper是一个轻量级的O/R框架,性能强劲,支持原生sql与模型对象混合写法,并且是半自动的,通过DapperExtension插件可以实现纯模型的操作(零Sql)语句,但是处理多表联查时性能不如EF,毕竟EF是微软的亲儿子。
特点 :

  • 轻量。只有一个文件(SqlMapper.cs),编译完成之后只有120k(好象是变胖了)
  • 速度快。Dapper的速度接近与IDataReader,取列表的数据超过了DataTable。
  • 支持多种数据库。Dapper可以在所有Ado.net Providers下工作,包括sqlite, sqlce, firebird, oracle, MySQL, PostgreSQL and SQL Server
  • 可以映射一对一,一对多,多对多等多种关系。
  • 性能高。通过Emit反射IDataReader的序列队列,来快速的得到和产生对象,性能不错。
  • 支持FrameWork2.0,3.0,3.5,4.0,4.5

性能对比

SqlSugar 和 dapper 性能对比

在这里插入图片描述

查询一万次数据并带查询条件
在这里插入图片描述

多表连接查询一千次无查询条件
在这里插入图片描述
查询一万次不带条件
在这里插入图片描述
CPU使用情况
在这里插入图片描述
多表联查执行一万次(这里就可以看出EF的优势了)

在这里插入图片描述

C# 代码性能优化

IEnumerable

list 继承自 IEnumerable 所以可以用父类对象接收子类的数据 看下面代码段A 和代码段B。A段代码多了一个ToList的操作。所以代码段B性能更胜一筹

      
List<string> fruits = new List<string> {
    
     "apple", "passionfruit", "banana", "mango",
                    "orange", "blueberry", "grape", "strawberry" };
                    //A
             List<string> query = fruits.Where(fruit => fruit.Length < 6).ToList();
             //B
            IEnumerable<string> query = fruits.Where(fruit => fruit.Length < 6);
            foreach (string fruit in query)
                Console.WriteLine(fruit);

Lazy< T >

Lazy延时加载类, 延时加载(延时实例化或延时初始化)重点是延时,用时加载。意思是对象在使用的时候创建而不是在实例化的的时候才创建。

对于一个引用类型的T运行时要在堆上开辟空间,必然耗时。
Lazy的出现就意味着解决性能,对于创建的对象开销大,而第一次加载并不使用,后期才能用到,体现出了延时性,提高了启动速度。

延时加载主要应用的场景:

  • 数据层(ADO.NET或Entity Framework等ORM,Java里面的Hibernate也用到了这种技术)
  • 反射(加载assemblier,type,MEF)
  • 缓存对象,领域实体

微软官方文档:传送门

// 写一个model
class LargeObject
{
    
    
    public int InitializedBy {
    
     get {
    
     return initBy; } }

    int initBy = 0;
    public LargeObject(int initializedBy)
    {
    
    
        initBy = initializedBy;
        Console.WriteLine("LargeObject was created on thread id {0}.", initBy);
    }

    public long[] Data = new long[100000000];
}

// 这里是 lazy<T>的使用
class TestLazy
{
    
    
    Lazy<LargeObject> lazyLargeObject = null;

    public TestLazy()
    {
    
    
        //创建一个延迟加载对象
        lazyLargeObject = new Lazy<LargeObject>(InitLargeObject);
    }

    public void ReallyLoad()
    {
    
    
        //此时真正加载
        lazyLargeObject.Value;
        Console.WriteLine("lazy load big object");

        //do something
    }
}

void Test()
{
    
    
    TestLazy t = new TestLazy();
    t.ReallyLoad(); //这时,真正延迟加载时才会打印"lazy load big object"
}

C#大量数据做聚合的处理方案

不要直接用DataTable做聚合。先用sql语句把数据查询出来然后转为List对象数组然后再去做聚合。或者读取的时候直接用ORM框架读取出来得到对象数据再做聚合。

//用sql语句获取数据然后转为对象数组
public List<model> GetData()
{
    
    
	List<model> list = new List<model> ();
	DataTable ds_rtn;
	try{
    
    
		string sql="select id,par,tem from table where GcFlag=0";
		lock(DBLock)
		{
    
    
		ds_rtn=db.ReturnDataTable(sql);
		}
         for(int i=o;i<ds_rtn.Rows.Count;i++)
             {
    
    
                model   m=new  model();
				m.id=(int)ds_rtn[i]["id"];
				m.par=(int)ds_rtn[i]["par"];
				m.tem=ds_rtn[i]["tem"].Tostring();
				list.add(model); 
				}
			 ds_rtn.Dispose();

	}Catch(Exception ex)
	{
    
    
	//写日志
	}
}

C# 做大量数据导入数据库

使用 SqlBulkCopy
//这是我用到的表
在这里插入图片描述
创建DataTable 注意这里的顺序要和数据库中表里键的顺序一致,包括类型也要一致,还有就是表里的每个字段都要有


											 DataTable InsDt = new DataTable();
                                            InsDt.Columns.Add("id", typeof(int));
                                            InsDt.Columns.Add("skuid", typeof(string));
                                            InsDt.Columns.Add("placepointid", typeof(string));
                                            InsDt.Columns.Add("product_spec_id", typeof(string));
                                            InsDt.Columns.Add("sale_price", typeof(int));
                                            InsDt.Columns.Add("sku_spec_custom_id", typeof(string));
                                            InsDt.Columns.Add("sku_spec_id", typeof(string));
                                            InsDt.Columns.Add("upc", typeof(string));
                                            InsDt.Columns.Add("weight", typeof(int));
                                            InsDt.Columns.Add("Createtime", typeof(DateTime));

								//im.sku_spec是数据源
 									foreach (var item in im.sku_spec)
                                            {
    
    

                                                DataRow row = InsDt.NewRow();
                                                row["skuid"] = im.sku_id.ToString();
                                                row["placepointid"] = storeid;
                                                row["product_spec_id"] = item.product_spec_id.ToString();
                                                row["sale_price"] = int.Parse(item.sale_price.ToString());
                                                row["sku_spec_custom_id"] = item.sku_spec_custom_id.ToString();
                                                row["sku_spec_id"] = item.sku_spec_id.ToString();
                                                row["upc"] = item.upc.ToString();
                                                row["weight"] = int.Parse(item.weight.ToString());
                                                row["Createtime"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
                                                InsDt.Rows.Add(row);
											}



						//调用方法 参数一是和表结构一样的DataTable,参数二是数据库中的表的名称
					 db.BatchInsert(InsDt, "MedicineInfo_ele_Sku");

这里是BatchInsert方法

 public static void BatchInsert(DataTable dt, string tableName)
        {
    
    
            string connstr = Properties.Settings.Default.lswxConnectionString;
            using (SqlConnection conn = new SqlConnection(connstr))
            {
    
    
                Stopwatch sw = new Stopwatch();
                SqlBulkCopy bulkCopy = new SqlBulkCopy(conn);
                bulkCopy.DestinationTableName = tableName;
                bulkCopy.BatchSize = dt.Rows.Count;
                conn.Open();
                sw.Start();
                if (dt != null)
                {
    
    
                    bulkCopy.WriteToServer(dt);
                    sw.Stop();
                }
                conn.Close();
            }
        }

Guess you like

Origin blog.csdn.net/qq_42455262/article/details/120016448