最近在面試,總結一下問的比較多的問題,持續補充哈!
基礎varchar與char區別
首先你要知道的是varchar(20),這裡的20代表的是字元,而不是位元組,其次在mysql中,所有使用utf8字符集,無論是中文還是英文,都是按照3個位元組儲存
varchar與char都可以儲存字元,它們的區別是
char是定長字元,建立表時定義多少長度,就分配多少的儲存空間;varchar是可變長字元,占用的儲存空間與實際儲存的字元長度對應。。。。
char最多可以儲存255個字元,而varchar最多可以儲存65535個位元組,在utf-8下可以儲存65535/3個字元
char會取出多餘的空格,varchar不會
雖然varchar是可變長字元,那是不是意味我們定義時長度就可以隨便寫呢?答案是不可以,原因如下:
mysql最大列的長度為65535位元組,如果超出了會報錯,text/blob除外
雖然占用的空間是實際值的長度,但是讀取到記憶體時,還是需要分配指定大小的空間
int(1)和int(20)的區別
首先你要知道的是int(1)和int(10),這裡的10代表的是寬度,而不是限制取值範圍,比如int(1),你依然可以儲存10000,這裡的寬度表示如果你的寬度不足會用空格表示,只不過客戶端預設不顯示空格,你可以用zerofill來將空格替換為0,不過這個功能是個雞肋,一般不用。
如果想要限制值的取值範圍,可以選擇不同的數值型別,比如tinyint限制為128,smallint限制到32767,如果是無符號位的話還可以再擴大一倍,不過就不能儲存負數了。
decimal儲存金額
對於金額的處理解決不能使用float或者double,因為計算機是用二進位制儲存資料的,無法精確的表達浮點數
有三種方案:
decimal(m,d),m代表資料總長度,d代表小數長度,預設是10,0
decimal的計算是由mysql處理的,所以效能不如浮點數和整數計算快
bigint儲存分:第二選擇,優先選擇decimal
varchar:不建議,因為沒有約束。
索引慢查詢日誌
1.開啟慢查詢日誌 slow
2.設定記錄時間的閾值 設定為1秒
複製**
分析慢查詢
explain
重點關注 type
複製**
優化索引提高資料檢索和排序的效率
分析查詢效率
統計查詢慢的sql,開啟慢查詢日誌,將query_time設定為1秒
通過explain分析sql,主要關注type、key、key_len、rows、extra
type:查詢的型別,一般優化到index,range,ref,盡量避免all全表掃瞄
ref:基於普通索引的等值查詢
range:基於索引的範圍查詢
index:全索引掃瞄
all:不走索引,全表掃瞄
key:實際選擇的索引
key_len:檢視聯合索引被選擇了幾列
rows:掃瞄的行數
extra:附加資訊,有沒有磁碟排序
索引失效場景
1.對索引列使用函式
對索引列使用函式會導致索引失效,走全表掃瞄
原因:這是因為sql執行的過程中會將所有值經過函式計算後生成新的集合和條件,然後再進行比較。而索引中儲存的是原有值的集合,所以無法使用索引過率
2. 隱式轉換
隱式轉換即操作符左右兩邊是不同型別的物件,就需要型別轉換保證相容,比如表中有乙個欄位是varchar型別的,然後比較的時候沒有注意寫成了int型別,就會發生隱式轉換,走全表掃瞄
原因:還是因為使用了函式,因為mysql會使用cast函式對列進行轉換
解決辦法:避免隱式轉換
3.模糊查詢
萬用字元在前面無法使用索引查詢
解決辦法:萬用字元放右邊或者使用其他的搜尋工具,結合實際情況解決
4.範圍查詢
範圍過大會走全表掃瞄
原因:優化器會根據表大小、i/o大小評估是否使用索引
解決辦法:分多次查詢使用union合併
5.計算操作
原因:對索引列進行計算操作無法使用索引
解決辦法:計算操作放在等號後面或者通過**實現,不要在資料庫層進行計算操作
排序優化
mysql中的排序有兩種:索引排序和file sort排序,應該盡量使用索引排序
file sort排序可能在磁碟中,也可能在記憶體中,與引數sort_buffer_size有關
order by
對排序欄位加索引,如果有多個排序字段,那麼就建立聯合索引
對於先等值查詢再排序的兩個字段,建立聯合索引
去掉不必要的返回字段,如果返回字段包含了非排序字段,那麼會不走索引,因為掃瞄全部索引並查詢沒有索引的行比全表掃瞄效率要低,所以會放棄走索引
⚠️ 對於先範圍查詢再排序的字段,即使建立了聯合索引也不會使用索引排序,比如where a > 1000 order by b,因為對於單個a的值,b是有序的,而對於範圍a的值,b不是有序的,所以需要額外排序
group by
預設情況下,group by會對分組排序,它的優化和order by一樣,如果不需要排序的話,可以order by null
select
複製**
分頁優化
limit 10000,10,看似查詢10條記錄,其實是查詢了100010條記錄,然後拋棄了前10000條,如果資料量很大,那效率就會很低,兩種優化方式:
基於自增主鍵排序的分頁查詢,根據主鍵進行非等值篩選id > 10000 limit 10,但是如果刪除了前面的記錄,結果就會不準確
基於非自增主鍵分頁查詢,先根據索引排序查出id值,然後與原表進行管理。如果你直接根據非自增主鍵排序返回字段,根據前面講到的order by場景如果返回了非排序字段,那是不會走索引的。
join優化
為關聯字段新增索引,因為:mysql關聯查詢有兩個演算法:nlj和bnlj
nlj是迴圈驅動表取出每行資料,然後與被驅動表進行匹配,假如驅動表有100條資料,被驅動表有10000條資料,那麼它的磁碟掃瞄的行數就是100萬。
bnlj是將驅動表讀取到join buffer記憶體中,然後與被驅動表匹配,它磁碟掃瞄的次數時100+10000次,記憶體中判斷的次數時100次。
mysql中只有在關聯欄位有索引的情況下才會使用nlj演算法,不然效率太低了。而沒有索引的情況下會使用bnlj演算法
預設情況下優化器會選擇小表作為驅動表
count優化
mysql中統計表的總行數使用count(),有以下幾種方式:
count(列):只會統計非null的行
count(*):統計所有行
count(1):統計所有行,count(*)和count(1)效能上並沒有區別
優化有兩個層面:
針對於當前表建立普通索引:如果我們使用count(*)統計資料時候,可以在表中建立乙個普通索引,那麼統計的時候就回去掃瞄普通索引樹。因為普通索引樹比主鍵索引樹要小,所以優化器會優先選擇普通索引樹!
如果我們資料量非常大並且經常需要統計的話可以單獨維護乙個計數表,有兩個字段,分別是表名和表的數量,每次增刪改的時候去維護技術表,當統計時直接查詢技術表的數量
快速匯入大批資料
首先insert資料的時間有一半都在客戶端與伺服器的連線通訊上,所以我們可以一次inset多個值,也就是避免每次新增資料都要進行連線
關閉事務的自動提交,多條insert語句合併提交可以提高效率鎖事務
其他主鍵選擇自增還是uuid
首先mysql它是基於主鍵構建一顆b+樹,葉子節點有序存放整行的資料。如果沒有設定主鍵會選擇非null的唯一索引或者row id
如果使用uuid的話它生成的值是隨機的,插入資料時就會導致頁**,插入資料的效率就會降低,因為需要重新維護它的排序
自增主鍵用完了怎麼辦
分庫分表
mysqldump
-- 匯出資料
mysqldump -uroot -p'hvfish@1234' -h127.0.0.1 資料庫名 表名 > t1.sql
-- 匯入資料
mysql -uroot -p'hvfish@1234' -h127.0.0.1 表名
複製**
mysql建立索引面試題 MySQL索引 面試題
1 索引可以加快資料檢索操作,但會使資料修改操作變慢。每修改資料記錄,索引就必須重新整理一次。為了在某種程式上彌補這一缺陷,許 多sql命令都有乙個delay key write項。這個選項的作用是暫時制止mysql在該命令每插入一條新記錄和每修改一條現有之後立刻對索引進 行重新整理,對索引的重新整...
mysql優化面試總結
總結 1.資料庫的設計 盡量把資料庫設計的更小的佔磁碟空間.1 盡可能使用更小的整數型別.mediumint就比int更合適 2 盡可能的定義欄位為not null且設定預設值,除非這個字段需要null.3 只建立確實需要的索引。索引有利於檢索記錄,但是不利於快速儲存記錄。如果總是要在表的組合欄位上...
Mysql面試總結 索引
1.資料庫中最常見的慢查詢優化方式是什麼 2.為什麼加索引能優化慢查詢 3.哪些資料結構能夠提高查詢速度 4.為什麼這些資料結構能優化查詢速度 mysql還要選擇b 樹 索引是幫助mysql高效獲取資料的資料結構 索引儲存在檔案系統中 索引的檔案儲存形式與儲存引擎相關 索引的結構 hash 二叉樹b...