1.索引
作用:
- 約束
- 加速查找
索引分類(約束):
- 普通索引:加速查找
- 主鍵索引:加速查找 + 不能為空 + 不能重複
- 唯一索引:加速查找 + 不能重複
- 聯合索引(多列) :
- 聯合主鍵索引
- 聯合唯一索引
- 聯合普通索引
索引分類(加速查找):
hash索引:
索引表存儲(哈希值的順序和數據表中的數據順序不相同):
1.所有索引列數據轉換成的哈希值
2.索引列數據的內存地址
hash索引優點:
查找單個值快
查找範圍值慢
btree索引:二叉樹(innodb)
二叉樹存儲:
先將索引列數據轉化成數字,每個二叉樹節點存儲一個數字及索引列數據的地址,
二叉樹節點的數字與子節點的數字有順序關係(左子節點數字小於父節點,有子節點數字大於父節點)
hash索引優點:
查找單個值慢
查找範圍值快
建立索引:
- a.額外的文件保存特殊的數據結構
- b.查詢加快,插入更新刪除相對也會變慢
- c.命中索引(此處email列建立了索引)
select * from userinfo where email = 'asdf';
# 由於未命中索引,查詢速度慢
select * from userinfo where email like 'asdf';
普通索引:
- create index 索引名稱 on 表名(列名)
- drop index 索引名稱 on 表名
唯一索引:
- create unique index 索引名稱 on 表名(列名)
- drop unique index 索引名稱 on 表名
組合(唯一)索引:
- create unique index 索引名稱 on 表名(列名,列名)
- drop index 索引名稱 on 表名
- create unique index ix on userinfo3(name,email);
- 最左前綴匹配(組合索引(name,email))
select * from userinfo3 where name='alex';
select * from userinfo3 where name='alex' and email='asdfg';
# 無法使用索引,組合索引會優先匹配組合中左邊的列
select * from userinfo3 where email='asdfg';
組合索引效率>索引合併
名詞:
覆蓋索引:
- 在索引文件中直接獲取數據(此處sid是索引)
select sid from userinfo where sid = 5;
索引合併:
- 把多個單列索引合併使用,對多列單獨建立索引一起使用
select * from userinfo3 where name='alex' and email='asdfg';
部分索引(text類的使用短索引):
create index ix__ on tb1(title(15)) 表示對title列前15個字符進行索引
2.不能命中索引情況:
- like '%xx'
# name是索引,但是使用like和通配符進行查找,不能命中索引
select * from tb1 where name like '%cn';
- 使用函數
# email是索引,但是使用reverse函數後不會命中索引
select * from tb1 where reverse(email) = 'alex155@163.com';
- or(僅當or中沒有建立索引的列才會不使用索引)
# nid是索引 name不是索引 email是索引
select * from tb1 where nid = 1 or name = 'alex';
# 以下會走索引
select * from tb1 where nid = 1 or email = 'seven@live.com' and name = 'alex'
- 類型不一致(主鍵除外)
# nid int類型,name是varcha類型
select * from tb1 where nid = 1 or name = 888;
- !=(主鍵除外)
# name是索引,使用!=不能命中索引
select * from tb1 where name != 'alex';
- >(主鍵和整數類型除外)
# name是索引,使用>不能命中索引
select * from tb1 where name >'alex';
- order by(主鍵除外)
# 當根據索引排序時候,選擇的映射如果不是索引,則不走索引
select name from tb1 order by email desc;
3.其他注意事項(不同的數據庫情況不同)
- 避免使用select *
- count(1)或count(列) 代替 count(*)
- 創建表時儘量時 char 代替 varchar
- 表的字段順序固定長度的字段優先
- 組合索引代替多個單列索引(經常使用多個條件查詢時)
- 儘量使用短索引
- 使用連接(JOIN)來代替子查詢(Sub-Queries)
- 連表時注意條件類型需一致
- 索引散列值(重複少)不適合建索引,例:性別不適合
4.時間
執行計劃(explain):讓mysql預估執行操作
查詢時的訪問方式:
性能:all < index < range < index_merge < ref_or_null < ref < eq_ref < system/const
慢:
explain select * from userinfo3 where name = 'alex'
type = all(全表掃描)
快:
explain select * from userinfo3 where email = 'alex'
type = ref(索引查找)
5.DBA工作
慢日誌
- 執行時間 >10
- 未命中索引
- 日誌文件路徑
配置
- 在內存中設置
# 查詢變量
show variables like '%query%'
show variables like '%queries%'
# 打開慢查詢日誌
set global slow_query_log = ON
# 記錄沒有使用索引的SQL
set global log_queries_not_using_indexes = ON
# 設置慢日誌文件存儲地址
set slow_query_log_file = D:/....
- 在配置文件中設置(啓動客户達端時可以指定配置文件的地址)
注意:修改配置文件之後,需要重啓服務
mysqld --defaults-file = 'D:\my.conf'
my.conf中添加內容:
# 打開慢查詢日誌
slow_query_log = ON
# 記錄沒有使用索引的SQL
set global log_queries_not_using_indexes = ON
# 設置慢日誌文件存儲地址
slow_query_log_file = D:/....
6.分頁(基於數據庫實現類似網頁中的分頁功能)
問題:同時對大量的數據進行分頁會浪費很多時間
方案一:只給用户看到若干頁面
缺點:這樣不能在根本上解決問題
方案二:索引表
缺點:在索引中掃描比在數據表中速度快,但是實際上不能加快很多,本質上還得掃描200000條數據
select * from userinfo3 where id in(select id from userinfo3 limit 200000,10);
方案三:記錄當前頁
(id不一定連續,所以無法直接使用id範圍進行查找)
1.頁面只有上一頁,下一頁
# max_id 當前頁面的最大id
# min_id 當前頁面的最小id
下一頁
select * from userinfo3 where id > max_id limit 10;
上一頁
select * from userinfo3 where id < max_id order by desc limit 10;
2.上一頁 192 193 196 197 198 199 x下一頁
# 當前處於193頁,需要跳到196頁
select * from userinfo3 where id in (
select id from (select * from userinfo3 where id > max_id limit 30) as N order by N.id desc limit 10;
)
本文章為轉載內容,我們尊重原作者對文章享有的著作權。如有內容錯誤或侵權問題,歡迎原作者聯繫我們進行內容更正或刪除文章。