常見mysql優化 面試題
優化哪些方面
1.表設計上
正規化,儲存引擎,欄位型別
2.功能上
索引,快取,分割槽
3.sql語句上
合理sql,經驗
4.架構上
主從複製,負載均衡,讀寫分離
儲存引擎
儲存引擎是真正儲存資料的地方
Mysql 5.5
1 不支援事務
2 表級鎖
3 資料和索引是分開儲存
4 insert ,select 適合高速插入和檢索。(bbs,部落格)
5 可壓縮
6 全文索引(全文搜尋)full index
快 糙 猛 php mysql
壓縮
INnodb
*************************** 8. row ***************************
Engine: InnoDB
- 事務處理
- 行級鎖 併發性
- 按照主鍵排序
- 外來鍵,維護資料完整性 (逐漸淡化)
- 考慮CPU效率和處理大資料的最佳效能
- 資料和索引一塊儲存
- 5.6.4開始支援全文索引
Innodb表的檔案
ibdata1 這是所有的innodb表的表空間檔案
開啟這個選項(mysql 5.6自動開啟)
mysql> show variables like 'innodb_file_per_table%';
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| innodb_file_per_table | ON |
+-----------------------+-------+
1 row in set (0.00 sec)
鎖的概念
出現爭奪資源。
讀鎖. 共享鎖. 一個程序在讀取某表的時候,另一個程序也可以讀取.但是當前程序僅僅能讀取這個表,而不能操作其他表.
寫鎖. 獨佔鎖. 一個程序在寫表時,是不允許另一個程序寫,當前程序僅僅能操作這一個表.
鎖的範圍,精細程度上。
Myisam表是表級鎖。 Innodb是行級鎖。
表級鎖: 開銷小,加鎖時間短。
行級鎖:相反。
Myisam和innodb的比較
Innodb:資料完整性,併發性好。事務,且是預設表引擎
適合銀行轉賬,等資料安全要求高的應用
- Myisam:壓縮儲存,適合 insert和select多的應用,部落格,BBS等
- 高速併發插入,
- 壓縮:
- 壓縮後的資料
- 壓縮後,不能再對錶進行寫操作
- 解壓縮
除非考慮到innodb不支援的特性,否則就優先選擇innodb儲存引擎。
其他的儲存引擎
- Archive
- 歸檔型。 Insert select 日誌
- Memory
- 記憶體型.支援insert,update,delete,select.資料不能過大。
- merge
- 合併多個相同結構的myisam表。
- 應用於 專案中的水平拆分。單表記錄過大。
索引
索引也是一種結構。從資料記錄裡提取出關鍵字,可以是某列,某些列,或者是列的一部分。關鍵字和資料記錄仍然保持原來的關聯關係。
刪除索引
alter table mycom drop index comnum
去除索引的情況
索引的種類
索引 某列,某些列,某列的部分。
- Primary 主鍵索引 不重複,不為空,不能為0
- Key 普通索引 沒什麼要求
- Unique 唯一索引 不重複,可以為null,
- Fulltext 全文索引 列是 varchar,char,text.沒什麼要求。 關鍵字來自列的部分
共同點:都是從資料記錄裡提取出的關鍵字。都為了查詢提速。
差異性:就是關鍵字的要求不同。
複合索引。 關鍵字來源於多個列。
字首索引。 關鍵字來自於某列的前N個字元。
索引的使用
@ SQL執行計劃 explain
使用索引時的情況。
explain select * from mycom where con=12345656
沒有使用索引時的結果
Mysql 5.5之前,explain只能針對select,現在insert ,update,delete都可以。
@ 檢索資料時使用 where
Where 欄位名=欄位值,
加索引的列,數值分佈比較廣泛。Where sex=’1’分佈不廣泛。
索引是佔據硬碟空間。影響寫資料的速度。
@ 排序時也可以使用 order by
排序欄位comname加上了索引後
Using filesort 排序 。外部排序(硬碟上,mysql使用order by ). (內部排序,氣泡排序是一個例子)
@索引覆蓋
查詢時索引覆蓋了資料。
查詢的資料,直接在索引中就有,而索引在記憶體中,查詢時候不需要去資料區中檢索,直接在索引中就可以查到。
使用索引需要注意的地方
列獨立
左原則
複合索引中,查詢時只要用到了最左邊的列,就能應用上索引。
Like ‘abc%’,’abcd_%’ 只要以確定的字元開始的,也可以使用索引。
Order by
Or
Or兩端的欄位,必須都建立索引,才有可能使用。
列型別是字串,字元常量沒有使用引號
Name Varchar,char(),’abcdef’,’123456’
Select * from user where name=’123456’ //name欄位建立索引,就會使用。
Select * from user where name=123456 //有可能不使用索引
存在索引,使用也正確,但是不使用
Select * from user where col>1 and <90 (均勻分佈時)
Select * from mycom where comnum > 12990
Mysql智慧化的選擇結果。
Mysql覺得 在索引和資料之間來回切換,造成的開銷比實際使用索引要大,放棄使用索引。
全文索引
解決like
Like ‘%美食%’;
Field regexp ‘’;
全表掃描。
Fulltext
使用全文索引的方式查詢
全文索引預設不支援中文,因為:
- 英文天然以空格為區分,分割符。中文沒有。
- 中文分詞。有一套關鍵字詞庫。
- Sphinx,可以作為mysql外掛來使用。只支援俄文和英文,Coreseek中文包。
- lucence
- 核心功能:建立全文索引,中文分詞。
字首索引
關鍵字的提取,是某個列的前N個字元
前N個字元,所達到的辨識度無限接近於使用整個欄位達到的辨識度。
Create Index 索引名 on 表名 (field(N))
N到底是多少?
經過測試 N=9
Create index preindex on mycom (pass(9))
索引覆蓋。應用不了字首索引。
其他優化的地方
只查詢相關的列
Select id,name,
一旦涉及到資料庫遷移,或者表結構修改等情況下,會造成大面積的修改程式碼。
慎用select *
節省頻寬的功能。
分解複雜查詢
禁用子查詢,join.。這些操作涉及鎖。影響併發。
不宜建立索引的列
優化group by
使用order by null 避免group by 時預設的排序
優化insert
Insert into test values(1,2),(3,4) 多個value的情況
分割槽
適合資料量1億條以上的表。
Mysql 5.1
Show variables like ‘%partition%’
Show plugins;
*************************** 42. row ***************************
Name: partition
Status: ACTIVE
Type: STORAGE ENGINE
Library: NULL
License: GPL
Partition
分割槽語法
Create table
Key(),hash(),list(),range()
查詢快取
mysql> show variables like '%query_cache%';
+------------------------------+---------+
| Variable_name | Value |
+------------------------------+---------+
| have_query_cache | YES |
| query_cache_limit | 1048576 |
| query_cache_min_res_unit | 4096 |
| query_cache_size | 1048576 |
| query_cache_type | OFF | //是否開啟查詢快取
| query_cache_wlock_invalidate | OFF |
+------------------------------+---------+
6 rows in set (0.00 sec)
需要在配置檔案設定 query_cache_type=On|1
慢查詢日誌
可以為當前程序開啟。
慢查詢日誌,不是優化措施,它可以幫助我們找到那些查詢超過某個時間點的SQl語句。