作者:jiahui07
鏈接:https://blog.csdn.net/qq_36691683/article/details/8929726
閱讀本文需要5分鐘
目錄
1蹭沛、多線程插入(單表)
2酪穿、多線程插入(多表)
3蝴悉、預(yù)處理SQL
4、多值插入SQL
5锐帜、事務(wù)(N條提交一次)
多線程插入(單表)
問:為何對(duì)同一個(gè)表的插入多線程會(huì)比單線程快田盈?同一時(shí)間對(duì)一個(gè)表的寫操作不應(yīng)該是獨(dú)占的嗎?
答:在數(shù)據(jù)里做插入操作的時(shí)候缴阎,整體時(shí)間的分配是這樣的:
1允瞧、多鏈接耗時(shí) (30%)
2、多發(fā)送query到服務(wù)器 (20%)
3药蜻、多解析query (20%)
4瓷式、多插入操作 (10% * 詞條數(shù)目)
5、多插入index (10% * Index的數(shù)目)
6语泽、多關(guān)閉鏈接 (10%)
從這里可以看出來贸典,真正耗時(shí)的不是操作,而是鏈接踱卵,解析的過程廊驼。
MySQL插入數(shù)據(jù)在寫階段是獨(dú)占的,但是插入一條數(shù)據(jù)仍然需要解析惋砂、計(jì)算妒挎、最后才進(jìn)行寫處理,比如要給每一條記錄分配自增id西饵,校驗(yàn)主鍵唯一鍵屬性酝掩,或者其他一些邏輯處理,都是需要計(jì)算的眷柔,所以說多線程能夠提高效率期虾。
多線程插入(多表)
分區(qū)分表后使用多線程插入。
預(yù)處理SQL
普通SQL:即使用Statement接口執(zhí)行SQL
預(yù)處理SQL:即使用PreparedStatement接口執(zhí)行SQL
使用PreparedStatement接口允許數(shù)據(jù)庫預(yù)編譯SQL語句驯嘱,以后只需傳入?yún)?shù)镶苞,避免了數(shù)據(jù)庫每次都編譯SQL語句,因此性能更好鞠评。
String sql = "insert into testdb.tuser (name, remark, createtime, updatetime) values (?, ?, ?, ?)";
for
(
int
i =
0
; i < m; i++) {
//從池中獲取連接
Connection
conn = myBroker.getConnection();
PreparedStatement
pstmt = conn.prepareStatement(sql);
for
(
int
k =
0
; k < n; k++) {
pstmt.setString(
1
,
RandomToolkit
.generateString(
12
));
pstmt.setString(
2
,
RandomToolkit
.generateString(
24
));
pstmt.setDate(
3
,
new
Date
(
System
.currentTimeMillis()));
pstmt.setDate(
4
,
new
Date
(
System
.currentTimeMillis()));
//加入批處理
pstmt.addBatch();
}
pstmt.executeBatch();
//執(zhí)行批處理
pstmt.close();
myBroker.freeConnection(conn);
//連接歸池
}
多值插入SQL
普通插入SQL:INSERT INTO TBL_TEST (id) VALUES(1)
多值插入SQL:INSERT INTO TBL_TEST (id) VALUES (1), (2), (3)
使用多值插入SQL茂蚓,SQL語句的總長度減少,即減少了網(wǎng)絡(luò)IO剃幌,同時(shí)也降低了連接次數(shù)聋涨,數(shù)據(jù)庫一次SQL解析,能夠插入多條數(shù)據(jù)负乡。
事務(wù)(N條提交一次)
在一個(gè)事務(wù)中提交大量INSERT語句可以提高性能牛郑。
1、將表的存儲(chǔ)引擎修改為myisam 2敬鬓、將 sql 拼接成字符串,每 1000 條左右提交事務(wù)。
執(zhí)行多條SQL語句钉答,實(shí)現(xiàn)數(shù)據(jù)庫事務(wù)础芍。
mysql數(shù)據(jù)庫
多條SQL語句
public void ExecuteSqlTran(List<string> SQLStringList)
{
using
(
MySqlConnection
conn =
new
MySqlConnection
(connectionString))
{
if
(
DBVariable
.flag)
{
conn.
Open
();
MySqlCommand
cmd =
new
MySqlCommand
();
cmd.
Connection
= conn;
MySqlTransaction
tx = conn.
BeginTransaction
();
cmd.
Transaction
= tx;
try
{
for
(
int
n =
0
; n <
SQLStringList
.
Count
; n++)
{
string
strsql =
SQLStringList
[n].
ToString
();
if
(strsql.
Trim
().
Length
>
1
)
{
cmd.
CommandText
= strsql;
cmd.
ExecuteNonQuery
();
}
//后來加上的
if
(n >
0
&& (n %
1000
==
0
|| n ==
SQLStringList
.
Count
-
1
))
{
tx.
Commit
();
tx = conn.
BeginTransaction
();
}
}
//tx.Commit();//原來一次性提交
}
catch
(
System
.
Data
.
SqlClient
.
SqlException
E)
{
tx.
Rollback
();
throw
new
Exception
(E.
Message
);
}
}
}
}
10w條數(shù)據(jù)大概用時(shí)10s!
參考資料:
https://www.cnblogs.com/aicro/p/3851434.html
http://blog.jobbole.com/29432/