1. 程式人生 > >mysql優化專題」90%程序員都會忽略的增刪改優化(2)

mysql優化專題」90%程序員都會忽略的增刪改優化(2)

硬盤 例如 ble sele 時間 刪除 好處 stat 思考

補充知識點:操作數據語句優化的認識

通常情況下,當訪問某張表的時候,讀取者首先必須獲取該表的鎖,如果有寫入操作到達,那麽寫入者一直等待讀取者完成操作(查詢開始之後就不能中斷,因此允許讀取者完成操作)。當讀取者完成對表的操作的時候,鎖就會被解除。如果寫入者正在等待的時候,另一個讀取操作到達了,該讀取操作也會被阻塞(block),因為默認的調度策略是寫入者優先於讀取者。當第一個讀取者完成操作並解放鎖後,寫入者開始操作,並且直到該寫入者完成操作,第二個讀取者才開始操作。因此:要提高MySQL的更新/插入效率,應首先考慮降低鎖的競爭,減少寫操作的等待時間。 (本專題在後面會討論表設計的優化)本篇,要講的優化是增刪改。

一、NSERT語句:

基本:INSERT [INTO] 表名 [(字段列表)] VALUES (值列表)[, (值列表), …]

註意:

如果要插入的值列表包含所有字段並且順序一致,則可以省略字段列表。

可同時插入多條數據記錄!

REPLACE 與 INSERT 完全一樣,可互換。

優化前例子:

技術分享

優化策略:

(1)當我們需要批量插入數據的時候,這樣的語句卻會出現性能問題。例如說,如果有需要插入100000條數據,那麽就需要有100000條insert語句,每一句都需要提交到關系引擎那裏去解析,優化,然後才能夠到達存儲引擎做真的插入工作。上述所說的同時插入多條就是一種優化。(經測試,大概10條同時插入是最高效的)

優化後例子:

技術分享

(2)將進程/線程數控制在2倍於CPU數目相對合適

(3)采用順序主鍵策略(例如自增主鍵,或者修改業務邏輯,讓插入的記錄盡可能順序主鍵)

(4)考慮使用replace 語句代替insert語句。(REPLACE語句請參考下文,有詳細講述)

二、DELETE語句:

DELETE FROM 表名[ 刪除條件子句](沒有條件子句,則會刪除全部)

例子:

技術分享

補充:Mysql中的truncate table和delete語句都可以刪除表裏面所有數據,但是在一些情況下有些不同!

例子:

truncate table gag;

(1)truncate table刪除速度更快,,但truncate table刪除後不記錄mysql日誌,不可以恢復數據。(謹慎使用)

(2)如果沒有外鍵關聯,innodb執行truncate是先drop table(原始表),再創建一個跟原始表一樣空表,速度要遠遠快於delete逐條刪除行記錄。(思考:刪除百萬級數據的時候是否可用truncate table)

(3)如果使用innodb_file_per_table參數,truncate table 能重新利用釋放的硬盤空間,在InnoDB Plugin中,truncate table為自動回收,如果不是用InnoDB Plugin,那麽需要使用optimize table來優化表,釋放空間。

truncate table刪除表後,optimize table尤其重要,特別是大數據數據庫,表空間可以得到釋放!

(4)表有外鍵關聯,truncate table刪除表數據為逐行刪除,如果外鍵指定級聯刪除(delete cascade),關聯的子表也會會被刪除所有表數據。如果外鍵未指定級聯(cascde),truncate table逐行刪除數據,如果是父行關聯子表行數據,將會報錯。

註意:

一個大的 DELETE 或 INSERT 操作,要非常小心,因為這兩個操作是會鎖表的,表一鎖住,其他操作就進不來了。因此,我們要交給DBA去拆分,重整數據庫策略,比如限制處理1000條。

另外,擴展下刪除和索引的聯系(關於索引優化,後面的查詢優化也會講解),由於索引需要額外的維護成本;因為索引文件是單獨存在的文件,所以當我們對數據的增加,修改,刪除,都會產生額外的對索引文件的操作,這些操作需要消耗額外的IO,會降低增/改/刪的執行效率。所以,在我們刪除數據庫百萬級別數據的時候,查詢MySQL官方手冊得知刪除數據的速度和創建的索引數量是成正比的。所以我們想要刪除百萬數據的時候可以先刪除索引(此時大概耗時三分多鐘),然後刪除其中無用數據,此過程需要不到兩分鐘,刪除完成後重新創建索引(此時數據較少了)創建索引也非常快,約十分鐘左右。與之前的直接刪除絕對是要快速很多,更別說萬一刪除中斷,一切刪除會回滾。那更是坑了。

三、UPDATE語句:

UPDATE 表名 SET 字段名=新值[, 字段名=新值] [更新條件]

例子:

技術分享

優化:更新多條記錄(往後會結合MyBatics寫個實例)

技術分享

更新多條記錄的多個值

技術分享

(1). 盡量不要修改主鍵字段。(廢話,反正我就從沒改過..)

(2). 當修改VARCHAR型字段時,盡量使用相同長度內容的值代替。

(3). 盡量最小化對於含有UPDATE觸發器的表的UPDATE操作。

(4). 避免UPDATE將要復制到其他數據庫的列。

(5). 避免UPDATE建有很多索引的列。

(6). 避免UPDATE在WHERE子句條件中的列。


四、REPLACE語句:

根據應用情況可以使用replace 語句代替insert/update語句。例如:如果一個表在一個字段上建立了唯一索引,當向這個表中使用已經存在的鍵值插入一條記錄,將會拋出一個主鍵沖突的錯誤。如果我們想用新記錄的值來覆蓋原來的記錄值時,就可以使用REPLACE語句。

使用REPLACE插入記錄時,如果記錄不重復(或往表裏插新記錄),REPLACE功能與INSERT一樣,如果存在重復記錄,REPLACE就使用新記錄的值來替換原來的記錄值。使用REPLACE的最大好處就是可以將DELETE和INSERT合二為一,形成一個原子操作。這樣就可以不必考慮同時使用DELETE和INSERT時添加事務等復雜操作了。

在使用REPLACE時,表中必須有唯一有一個PRIMARY KEY或UNIQUE索引,否則,使用一個REPLACE語句沒有意義。

用法:

(1)同INSERT

含義一:與普通INSERT一樣功能

REPLACE INTO score (change_type,score,user_id) VALUES (‘吃飯‘,10,1),(‘喝茶‘,10,1),(‘喝茶‘,10,1);

含義二:找到第一條記錄,用後面的值進行替換

REPLACE INTO score (id,change_type,score,user_id) VALUES (1,‘吃飯‘,10,1)

此語句的作用是向表table中插入3條記錄。如果主鍵id為1或2不存在就相當於插入語句:

INSERTINTO score (change_type,score,user_id) VALUES (‘吃飯’,10,1),(‘喝茶’,10,1),(‘喝茶’,10,1);

如果存在相同的值則不會插入數據。

(2)replace(object, search, replace),把object中出現search的全部替換為replace。

用法一:並不是修改數據,而只是單純做局部替換數據返還而已。

SELECT REPLACE(‘喝茶‘,‘茶‘,‘喝‘)//結果: 喝喝123

用法二:修改表數據啦,對應下面就是,根據change_type字段找到做任務的數據,用bb來替換

UPDATE score SET change_type=REPLACE(change_type,‘做任務‘,‘bb‘)1

在此,做下對比:UPDATE和REPLACE的區別:

1)UPDATE在沒有匹配記錄時什麽都不做,而REPLACE在有重復記錄時更新,在沒有重復記錄時插入。

2)UPDATE可以選擇性地更新記錄的一部分字段。而REPLACE在發現有重復記錄時就將這條記錄徹底刪除,再插入新的記錄。也就是說,將所有的字段都更新了。

其實REPLACE更像INSERT與DELETE的結合。

mysql優化專題」90%程序員都會忽略的增刪改優化(2)