1. 程式人生 > 其它 >mysql 基礎(sql優化)

mysql 基礎(sql優化)

插入優化
1. 批量插入

insert into tb_test values(1,'qwe'),(2,'qwe2'),(3,'qwe2');

2.手動事務提交

start transaction;
insert into tb_test values(1,'qwe'),(2,'qwe2'),(3,'qwe2');
insert into tb_test values(1,'qwe'),(2,'qwe2'),(3,'qwe2');
insert into tb_test values(1,'qwe'),(2,'qwe2'),(3,'qwe2');
commit;

3. 主鍵順序插入

4.大批量資料插入

 如果一次性需要插入大批量資料,使用insert語句插入效能較低,此時可以使用MySOL資料庫提供的load指令進行插入。

# 客戶端連線服務端時,加上引數-local-infile
mysql --local-infile -u root -p
# 檢視是否開啟
SELECT @@local_infile;
#設定全域性引數local infile為1,開啟從本地載入檔案匯入資料的開關
set global local_infile=1;
#執行load指令將準備好的資料,載入到表結構中
load data local infile '/root/sql1.log' into table tb_user fields terminated by ',' lines terminated by '\n';

主鍵優化

資料組織方式:
在InnoDB儲存引擎中,表資料都是根據主鍵順序組織存放的,這種儲存方式的表稱為 索引組織表

頁分裂 

頁可以為空,也可以填充一半,也可以填充100%,每個頁包含了2-N行資料(如果一行資料很大,會行溢位),根據主鍵排列

頁合併

當刪除一行記錄時,實際上記錄並沒有被物理刪除,只是記錄被標記為刪除並且它的空間變得允許被其他記錄宣告使用。
當頁中刪除的記錄達到 MERGE_THRESHOLD(預設為頁的 50%),InnoDB 會開始尋找最靠近的頁(前或後)看看是否可以將兩個頁合併以優化空間的使用

視訊地址:https://www.bilibili.com/video/BV1Kr4y1i7ru?p=90&spm_id_from=pageDriver

主鍵設計原則

  • 滿足業務需求的情況下,儘量降低主鍵的長度
  • 插入資料時,儘量選擇順序插入,選擇使用 AUTO_INCREMENT自增主鍵
  • 儘量不要使用UUID做主鍵或者是其他自然主鍵,如身份證號。
  • 業務操作時,避免對主鍵的修改

order by優化

Using filesort:通過表的索引或全表掃描,讀取滿足條件的資料行,然後在排序緩衝區 sort buffer 中完成排序操作,所有不是通過索引直接返回排序結果的排序 都叫 FileSort 排序

Using index通過有序索引順序掃描直接返回有序資料,不需要額外排序,操作效率高

多欄位排序時情況下,建立索引時若沒有指定欄位排列順序,那麼預設都是升序排列,若一個升序一個降序就會成為Using filesort

 解決辦法是新增一個排序的索引

create index idx_age_pho_ad on tb_user(age asc, phone desc);

 優化細節:

  • 根據排序欄位建立合適的索引,多欄位排序時,也遵循最左字首法則
  • 儘量使用覆蓋索引
  • 多欄位排序,一個升序一個降序,此時需要注意聯合索引在建立時的規則(ASC / DESC)
  • 如果不可避免的出現 filesort,大資料量排序時,可以適當增大排序緩衝區大小 sort_buffer_size(預設256k)

group by優化

在分組操作時,可以通過索引來提高效率

分組操作時,索引的使用也是滿足最左字首法則

limit 優化

一個常見又非常頭疼的問題就是 limit 2000000,10,此時需要MySQL排序前2000010記錄,僅僅返回2000000 - 2000010 的記錄,其他記錄丟棄,查詢排序的代價非常大。

優化思路:一般分頁查詢時,通過建立 覆蓋索引 能購比較好地提高效能,可以通過覆蓋索引加子查詢形式進行優化。

select * from tb_user t, (select id from tb_user order by id limit 2000000, 10) a where t.id=a.id;

先用limit查詢出主鍵id,這樣不用取出所有資料,提高了效率,再通過主鍵id進行索引查詢取出全部資料

count 優化

  • MyISAM 引擎把一個表的總行數存在了磁碟上,因此執行 count(*) 的時候會直接返回個數,效率很高。(前提是沒有 where 條件,否則效率也低)
  • InnoDB 引擎就麻煩一些,它執行 count(*) 的時候,需要把資料一行一行地從引擎裡面讀出來,然後累積計數

優化方案

count(主鍵)
  InnoDB 引擎會遍歷整張表,把每一行的 主鍵id 值都取出來,返回給服務層。服務層拿到主鍵後,直接按行進行累加(主鍵不可能為null)
count(欄位)
  沒有 not null 約束:InnoDB 引擎會遍歷整張表把每一行的欄位值都取出來,返回給服務層,服務層判斷是否為 null,不為 null,計數累加。
  有 not null 約束:InnoDB 引擎會遍歷整張表,把每一行的欄位值都取出來,返回給服務層,直接按行進行累加。
count(1)
  InnoDB 引擎遍歷整張表,但不取值。服務層對於返回的每一行,放一個數字“1”進去,直接按行進行累加
count(*)
  InnoDB 引擎並不會把全部欄位取出,而是專門做了優化,不取值,服務層直接按行進行累加
按照效率排序: count(欄位) < count(主鍵 id) < count(1) ≈ count(*)

update 優化

InnoDB 儲存引擎有一個特點,支援 行級鎖,所以這意味著當多個執行緒同時更新一張表時,若更新的行不同,則可以同時對該表進行更新修改;
同時介紹一下 表鎖,即多個執行緒要對錶進行修改的時候,不能同時修改,因為鎖住的是整張表,只能一個一個排著隊進行

所以 update 的優化,意味著要規避行鎖升級為表鎖
InnoDB 的行鎖是針對索引加的鎖,不是針對記錄加的鎖,並且該索引不能失效,否則會從行鎖升級為表鎖
根據索引欄位更新