mysql優化專題」90%程序員都會忽略的增刪改優化(2)
補充知識點:操作數據語句優化的認識
通常情況下,當訪問某張表的時候,讀取者首先必須獲取該表的鎖,如果有寫入操作到達,那麽寫入者一直等待讀取者完成操作(查詢開始之後就不能中斷,因此允許讀取者完成操作)。當讀取者完成對表的操作的時候,鎖就會被解除。如果寫入者正在等待的時候,另一個讀取操作到達了,該讀取操作也會被阻塞(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)