mirror of
https://github.com/dotnetcore/FreeSql.git
synced 2026-02-06 00:10:55 +08:00
update
1
Home.md
1
Home.md
@@ -48,6 +48,7 @@ FreeSql是一个功能强大的NETStandard库,用于对象关系映射程序(O
|
||||
* [日期/时间](https://github.com/2881099/FreeSql/wiki/%e8%a1%a8%e8%be%be%e5%bc%8f%e5%87%bd%e6%95%b0#%e6%97%a5%e6%9c%9f)
|
||||
* [其他](https://github.com/2881099/FreeSql/wiki/%e8%a1%a8%e8%be%be%e5%bc%8f%e5%87%bd%e6%95%b0#%e8%a1%a8%e8%be%be%e5%bc%8f%e5%87%bd%e6%95%b0%e5%85%a8%e8%a7%88)
|
||||
* [读写分离](https://github.com/2881099/FreeSql/wiki/%e8%af%bb%e5%86%99%e5%88%86%e7%a6%bb)
|
||||
* [性能](https://github.com/2881099/FreeSql/wiki/%e6%80%a7%e8%83%bd)
|
||||
* API参考
|
||||
|
||||
## 使用指南
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
* [日期/时间](https://github.com/2881099/FreeSql/wiki/%e8%a1%a8%e8%be%be%e5%bc%8f%e5%87%bd%e6%95%b0#%e6%97%a5%e6%9c%9f)
|
||||
* [其他](https://github.com/2881099/FreeSql/wiki/%e8%a1%a8%e8%be%be%e5%bc%8f%e5%87%bd%e6%95%b0#%e8%a1%a8%e8%be%be%e5%bc%8f%e5%87%bd%e6%95%b0%e5%85%a8%e8%a7%88)
|
||||
* [读写分离](https://github.com/2881099/FreeSql/wiki/%e8%af%bb%e5%86%99%e5%88%86%e7%a6%bb)
|
||||
* [性能](https://github.com/2881099/FreeSql/wiki/%e6%80%a7%e8%83%bd)
|
||||
* API参考
|
||||
|
||||
## 使用指南
|
||||
|
||||
40
分区分表.md
Normal file
40
分区分表.md
Normal file
@@ -0,0 +1,40 @@
|
||||
## 分区
|
||||
|
||||
分区就是把一个数据表的文件和索引分散存储在不同的物理文件中。把一张表的数据分成N多个区块,这些区块可以在同一个磁盘上,也可以在不同的磁盘上,数据库不同现实方式有所不同。
|
||||
|
||||
与分表不同,一张大表进行分区后,他还是一张表,不会变成二张表,但是他存放数据的区块变多了。分区的概念,我觉得就想突破磁盘I/O瓶颈,想提高磁盘的读写能力,来增加数据库的性能。
|
||||
|
||||
分区实现是比较简单的,建立分区表,根建平常的表没什么区别,并且对开发代码端来说是透明。
|
||||
|
||||
postgresql10以上的自动分区分表功能:
|
||||
|
||||
1、首先创建主分区表:
|
||||
```sql
|
||||
create table fenbiao(
|
||||
id int,
|
||||
year varchar
|
||||
) partition by list(year)
|
||||
```
|
||||
|
||||
这里设置的是根据year列进行数据分表;创建后使用navicat是看不到的;
|
||||
|
||||
2.创建分表:
|
||||
```sql
|
||||
create table fenbiao_2017 partition of fenbiao for values in ('2017');
|
||||
create table fenbiao_2018 partition of fenbiao for values in ('2018');
|
||||
```
|
||||
|
||||
这样这两天数据会依靠规则插入到不同分表中,如果插入一条不符合规则的数据,则会报错误:no partition of relation "fenbiao" found for row.
|
||||
|
||||
## 分表
|
||||
|
||||
分表从表面意思上看呢,就是把一张表分成N多个小表,每一个小表都是完正的一张表。分表后数据都是存放在分表里,总表只是一个外壳,存取数据发生在一个一个的分表里面。
|
||||
|
||||
分表后单表的并发能力提高了,磁盘I/O性能也提高了。并发能力为什么提高了呢,因为查寻一次所花的时间变短了,如果出现高并发的话,总表可以根据不同 的查询,将并发压力分到不同的小表里面。
|
||||
|
||||
## 分库分表
|
||||
|
||||
分库分表把原本存储于一个库的数据分块存储到多个库上,把原本存储于一个表的数据分块存储到多个表上。
|
||||
|
||||
数据库中的数据量不一定是可控的,在未进行分库分表的情况下,随着时间和业务的发展,库中的表会越来越多,表中的数据量也会越来越大,相应地,数据操作,增删改查的开销也会越来越大;另外,一台服务器的资源(CPU、磁盘、内存、IO等)是有限的,最终数据库所能承载的数据量、数据处理能力都将遭遇瓶颈。
|
||||
|
||||
135
性能.md
Normal file
135
性能.md
Normal file
@@ -0,0 +1,135 @@
|
||||
FreeSql现实了强大的功能的同时,性能并没有受影响,使用反射或耗时的操作都做了缓存处理。读取数据部分采用了ExpressionTree,使得FreeSql解析实体数据的速度与Dapper非常接近。
|
||||
|
||||
## 查询性能测试结果
|
||||
|
||||
```csharp
|
||||
IFreeSql mysql = new FreeSql.FreeSqlBuilder()
|
||||
.UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Max pool size=100")
|
||||
.UseLogger(new LoggerFactory().CreateLogger("FreeSql.MySql"))
|
||||
//由于null会默认输出日志到控制台,影响测试结果。这里传入一个空的日志输出对象
|
||||
.UseAutoSyncStructure(false)
|
||||
//关闭自动迁移功能
|
||||
.Build();
|
||||
|
||||
class Song {
|
||||
public int Id { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string Url { get; set; }
|
||||
public DateTime Create_time { get; set; }
|
||||
public bool Is_deleted { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
测试方法忽略第一次执行结果,以第二次执行结果为准。
|
||||
|
||||
| | 数量 | Dapper | FreeSql | |
|
||||
| - | - | - | - | - |
|
||||
| [执行SQL返回实体列表](#%e6%89%a7%e8%a1%8cSQL%e8%bf%94%e5%9b%9e%e5%ae%9e%e4%bd%93%e5%88%97%e8%a1%a8) | 131072 | 00:00:00.6234959 | 00:00:00.6470552 | |
|
||||
| [执行SQL返回元组列表](#%e6%89%a7%e8%a1%8cSQL%e8%bf%94%e5%9b%9e%e5%85%83%e7%bb%84%e5%88%97%e8%a1%a8) | 131072 | 00:00:00.4242411 | 00:00:00.5773532 | |
|
||||
| [执行SQL返回dynamic列表](#%e6%89%a7%e8%a1%8cSQL%e8%bf%94%e5%9b%9edynamic%e5%88%97%e8%a1%a8) | 131072 | 00:00:00.6448897 | 00:00:00.9447454 | (不推使用) |
|
||||
| [Dapper.Query VS FreeSql.ToList](Dapper.Query+VS+FreeSql.ToList) | 131072 | 00:00:00.6001112 | 00:00:00.6228980 | (使用频率最高)
|
||||
|
||||
好吧,FreeSql认输,你可能有疑问为什么比Dapper慢,总能看到某某orm宣称性能超过Dapper多少,都是Emit或ExpressionTree再比已经没有意义。
|
||||
|
||||
FreeSql支持更复杂的数据库类型解析,有一些类型需要递归或循环才能解析到正确的值,如果还说比Dapper快那是在欺骗自己和世界。
|
||||
|
||||
目前的性能可以说相差无及,并且真实项目的性能损耗更多不在这个环节,应该用更优的设计来提升性能。
|
||||
|
||||
> 由于Dapper没有批量插入/更新/删除的功能,并且都是执行一条SQL命令,测试结果没有意义。
|
||||
|
||||
> FreeSql批量插入使用的命令:INSERT INTO Song (...) VALUES(...),VALUES(...),VALUES(...)...
|
||||
|
||||
### 执行SQL返回实体列表
|
||||
|
||||
```csharp
|
||||
[Fact]
|
||||
public void QueryEntity() {
|
||||
var sb = new StringBuilder();
|
||||
var time = new Stopwatch();
|
||||
|
||||
time.Restart();
|
||||
List<Song> dplist1 = null;
|
||||
using (var conn = g.mysql.Ado.MasterPool.Get()) {
|
||||
dplist1 = Dapper.SqlMapper.Query<Song>(conn.Value, "select * from song").ToList();
|
||||
}
|
||||
time.Stop();
|
||||
sb.AppendLine($"Elapsed: {time.Elapsed}; Query Entity Counts: {dplist1.Count}; ORM: Dapper");
|
||||
|
||||
time.Restart();
|
||||
var t3 = g.mysql.Ado.Query<Song>("select * from song");
|
||||
time.Stop();
|
||||
sb.AppendLine($"Elapsed: {time.Elapsed}; Query Entity Counts: {t3.Count}; ORM: FreeSql*");
|
||||
}
|
||||
```
|
||||
|
||||
### 执行SQL返回元组列表
|
||||
|
||||
```csharp
|
||||
[Fact]
|
||||
public void QueryTuple() {
|
||||
var sb = new StringBuilder();
|
||||
var time = new Stopwatch();
|
||||
|
||||
time.Restart();
|
||||
List<(int, string, string)> dplist2 = null;
|
||||
using (var conn = g.mysql.Ado.MasterPool.Get()) {
|
||||
dplist2 = Dapper.SqlMapper.Query<(int, string, string)>(conn.Value, "select * from song").ToList();
|
||||
}
|
||||
time.Stop();
|
||||
sb.AppendLine($"Elapsed: {time.Elapsed}; Query Tuple Counts: {dplist2.Count}; ORM: Dapper");
|
||||
|
||||
time.Restart();
|
||||
var t4 = g.mysql.Ado.Query<(int, string, string)>("select * from song");
|
||||
time.Stop();
|
||||
sb.AppendLine($"Elapsed: {time.Elapsed}; Query Tuple Counts: {t4.Count}; ORM: FreeSql*");
|
||||
}
|
||||
```
|
||||
|
||||
### 执行SQL返回dynamic列表
|
||||
|
||||
```csharp
|
||||
[Fact]
|
||||
public void Query() {
|
||||
var sb = new StringBuilder();
|
||||
var time = new Stopwatch();
|
||||
|
||||
time.Restart();
|
||||
List<dynamic> dplist3 = null;
|
||||
using (var conn = g.mysql.Ado.MasterPool.Get()) {
|
||||
dplist3 = Dapper.SqlMapper.Query<dynamic>(conn.Value, "select * from song").ToList();
|
||||
}
|
||||
time.Stop();
|
||||
sb.AppendLine($"Elapsed: {time.Elapsed}; Query Dynamic Counts: {dplist3.Count}; ORM: Dapper");
|
||||
|
||||
time.Restart();
|
||||
var t5 = g.mysql.Ado.Query<dynamic>("select * from song");
|
||||
time.Stop();
|
||||
sb.AppendLine($"Elapsed: {time.Elapsed}; Query Dynamic Counts: {t3.Count}; ORM: FreeSql*");
|
||||
}
|
||||
```
|
||||
|
||||
### Dapper.Query VS FreeSql.ToList
|
||||
|
||||
```csharp
|
||||
[Fact]
|
||||
public void Query() {
|
||||
var sb = new StringBuilder();
|
||||
var time = new Stopwatch();
|
||||
|
||||
time.Restart();
|
||||
var t3 = g.mysql.Select<Song>().ToList();
|
||||
time.Stop();
|
||||
sb.AppendLine($"Elapsed: {time.Elapsed}; ToList Entity Counts: {t3.Count}; ORM: FreeSql*");
|
||||
|
||||
time.Restart();
|
||||
List<Song> dplist1 = null;
|
||||
using (var conn = g.mysql.Ado.MasterPool.Get()) {
|
||||
dplist1 = Dapper.SqlMapper.Query<Song>(conn.Value, "select * from song").ToList();
|
||||
}
|
||||
time.Stop();
|
||||
sb.AppendLine($"Elapsed: {time.Elapsed}; Query Entity Counts: {dplist1.Count}; ORM: Dapper");
|
||||
}
|
||||
```
|
||||
|
||||
> 更多测试源码:FreeSql/FreeSql.Tests.PerformanceTests/MySqlAdoTest.cs
|
||||
|
||||
Reference in New Issue
Block a user