索引快速查询
一、索引
索引是表的目錄,在查找內容之前可以先在目錄中查找索引位置,以此快速定位查詢數據。對于索引,會保存在額外的文件中。
名詞:
?????覆蓋索引:
??????- 在索引文件中直接獲取數據
?????
?????索引合并:
??????- 把多個單列索引文件合并使用???
MySQL中常見索引有:
- 普通索引
- 唯一索引
- 主鍵索引
- 組合索引
1、普通索引
普通索引僅有一個功能:加速查詢
create table in1(nid int not null auto_increment primary key,name varchar(32) not null, email varchar(64) not null, extra text, index ix_name (name) --普通索引,索引名(索引列) ) 創建表 + 索引創建索引
create index 索引名稱 on 表名(列名)
刪除索引
drop index 索引名稱 on 表名
查看索引
show index from table_name;
注意:對于創建索引時如果是BLOB 和 TEXT 類型,必須指定length。
create index ix_extra on in1(extra(32)); View Code2、唯一索引
唯一索引有兩個功能:加速查詢 和 唯一約束(可含null)
create table in1(nid int not null auto_increment primary key,name varchar(32) not null, email varchar(64) not null, extra text, unique ix_name (name) ) 創建表 + 唯一索引創建:
create unique index 索引名稱 on 表名(列名)
刪除:
drop unique index 索引名稱 on 表名
3、主鍵索引
主鍵有兩個功能:加速查詢 和 唯一約束(不可含null)
create table in1(nid int not null auto_increment primary key,name varchar(32) not null, email varchar(64) not null, extra text, index ix_name (name) ) OR create table in1( nid int not null auto_increment, name varchar(32) not null, email varchar(64) not null, extra text, primary key(ni1), index ix_name (name) ) 創建表 + 創建主鍵創建:
alter table 表名 add primary key(列名);
刪除:
alter table 表名 drop primary key; (刪除表的主鍵)
alter table 表名? modify? 列名 int, drop primary key;(刪除表指定列的主鍵)
4、組合索引
組合索引是將n個列組合成一個索引
- create unique index 索引名稱 on 表名(列名,列名)
- drop unique index 索引名稱 on 表名
其應用場景為:頻繁的同時使用n列來進行查詢,如:where n1 = 'alex' and n2 = 666。
create table in3(nid int not null auto_increment primary key,name varchar(32) not null, email varchar(64) not null, extra text ) 創建表 create index ix_name_email on in3(name,email); 創建組合索引如上創建組合索引之后,查詢(最左前綴匹配):(name,email)
- name and email? -- 使用索引
- name???????????????? -- 使用索引
- email???????????????? -- 不使用索引
注意:對于同時搜索n個條件時,組合索引的性能好于多個單一索引合并。
組合索引 - (name,email)select * from userinfo3 where name='alex' and email='asdf';select * from userinfo3 where name='alex';索引合并:- name- emailselect * from userinfo3 where name='alex' and email='asdf';select * from userinfo3 where name='alex';select * from userinfo3 where email='alex'; 組合索引和索引合并5、全文索引:對文本的內容進行分詞,進行搜索
?二、相關命令
- 查看表結構desc 表名- 查看生成表的SQLshow create table 表名- 查看索引show index from 表名三、正確使用索引
數據庫表中添加索引后確實會讓查詢速度起飛,但前提必須是正確的使用索引來查詢,如果以錯誤的方式使用,則即使建立索引也會不奏效。 ??? 即使建立索引,索引也不會生效:
id,enail創建索引- like '%xx' 沒有命中索引 select * from tb1 where email like '%cn'; - 使用函數select * from tb1 where reverse(email) = 'wupeiqi'; - orselect * from tb1 where nid = 1 or name = 'seven@live.com'; 無法命中索引(name列沒有建立索引) 特別的:當or條件中有未建立索引的列才失效,以下會走索引select * from tb1 where nid = 1 or name = 'seven@live.com' and email = 'alex'忽略name列(沒有創建索引)- 類型不一致如果列是字符串類型,傳入條件是必須用引號引起來,不然無法命中 select * from tb1 where email = 999;- !=select * from tb1 where email != 'alex'特別的:如果是主鍵,則還是會走索引select * from tb1 where nid != 123- >select * from tb1 where email > 'alex' 特別的:如果是主鍵或索引是整數類型,則還是會走索引select * from tb1 where nid > 123select * from tb1 where num > 123- order byselect name from tb1 order by email desc; (映射的是name列,所以不走索引)當根據索引排序時候,選擇的映射如果不是索引,則不走索引特別的:如果對主鍵排序,則還是走索引:select * from tb1 order by nid desc;- 組合索引最左前綴如果組合索引為:(name,email)name and email -- 使用索引name -- 使用索引email -- 不使用索引四、其他注意事項
- 避免使用select *- count(1)或count(列) 代替 count(*)- 創建表時盡量時 char 代替 varchar- 表的字段順序固定長度的字段優先- 組合索引代替多個單列索引(經常使用多個條件查詢時)- 盡量使用短索引- 使用連接(JOIN)來代替子查詢(Sub-Queries)- 連表時注意條件類型需一致- 索引散列值(重復少)不適合建索引,例:性別不適合五、limit分頁
無論是否有索引,limit分頁是一個值得關注的問題
a. select * from userinfo3 limit 20,10; b. - 不讓看(只能查看200頁)- 索引表中掃:1、select * from userinfo3 where id in(select id from userinfo3 limit 200000,10) 不是最優答案2、最優解決方案:記錄當前頁最大或最小ID1. 頁面只有上一頁,下一頁# max_id# min_id下一頁數據:select * from userinfo3 where id > max_id limit 10;上一頁數據:select * from userinfo3 where id < min_id order by id desc limit 10; id倒序速度很快2. 上一頁 192 193 [196] 197 198 199 下一頁 基于當前的頁面,點擊其他任一頁分頁select * from userinfo3 where id in (select id from (select id from userinfo3 where id > max_id limit 30) as N order by N.id desc limit 10) c.id不連續,所以無法直接使用id范圍進行查找 between ... and六、執行計劃
explain + 查詢SQL - 用于顯示SQL執行信息參數,根據參考信息可以進行SQL優化
讓mysql預估執行操作(一般正確)
mysql> explain select * from tb2; +----+-------------+-------+------+---------------+------+---------+------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+-------+ | 1 | SIMPLE | tb2 | ALL | NULL | NULL | NULL | NULL | 2 | NULL | +----+-------------+-------+------+---------------+------+---------+------+------+-------+ 1 row in set (0.00 sec) 查詢順序標識如:mysql> explain select * from (select nid,name from tb1 where nid < 10) as B;+----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 9 | NULL || 2 | DERIVED | tb1 | range | PRIMARY | PRIMARY | 8 | NULL | 9 | Using where |+----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+特別的:如果使用union連接氣值可能為nullselect_type查詢類型SIMPLE 簡單查詢PRIMARY 最外層查詢SUBQUERY 映射為子查詢DERIVED 子查詢UNION 聯合UNION RESULT 使用聯合的結果...table正在訪問的表名type查詢時的訪問方式,性能:all < index < range < index_merge < ref_or_null < ref < eq_ref < system/constALL 全表掃描,對于數據表從頭到尾找一遍select * from tb1;特別的:如果有limit限制,則找到之后就不在繼續向下掃描select * from tb1 where email = 'seven@live.com'select * from tb1 where email = 'seven@live.com' limit 1;雖然上述兩個語句都會進行全表掃描,第二句使用了limit,則找到一個后就不再繼續掃描。INDEX 全索引掃描,對索引從頭到尾找一遍select nid from tb1;RANGE 對索引列進行范圍查找select * from tb1 where name < 'alex';PS:between andin> >= < <= 操作注意:!= 和 > 符號INDEX_MERGE 合并索引,使用多個單列索引搜索select * from tb1 where name = 'alex' or nid in (11,22,33);REF 根據索引查找一個或多個值select * from tb1 where name = 'seven';EQ_REF 連接時使用primary key 或 unique類型select tb2.nid,tb1.name from tb2 left join tb1 on tb2.nid = tb1.nid;CONST 常量表最多有一個匹配行,因為僅有一行,在這行的列值可被優化器剩余部分認為是常數,const表很快,因為它們只讀取一次。select nid from tb1 where nid = 2 ;SYSTEM 系統表僅有一行(=系統表)。這是const聯接類型的一個特例。select * from (select nid from tb1 where nid = 1) as A;possible_keys可能使用的索引key真實使用的key_lenMySQL中使用索引字節長度rowsmysql估計為了找到所需的行而要讀取的行數 ------ 只是預估值extra該列包含MySQL解決查詢的詳細信息“Using index”此值表示mysql將使用覆蓋索引,以避免訪問表。不要把覆蓋索引和index訪問類型弄混了。“Using where”這意味著mysql服務器將在存儲引擎檢索行后再進行過濾,許多where條件里涉及索引中的列,當(并且如果)它讀取索引時,就能被存儲引擎檢驗,因此不是所有帶where子句的查詢都會顯示“Using where”。有時“Using where”的出現就是一個暗示:查詢可受益于不同的索引?!癠sing temporary”這意味著mysql在對查詢結果排序時會使用一個臨時表?!癠sing filesort”這意味著mysql會對結果使用一個外部索引排序,而不是按索引次序從表里讀取行。mysql有兩種文件排序算法,這兩種排序方式都可以在內存或者磁盤上完成,
explain不會告訴你mysql將使用哪一種文件排序,也不會告訴你排序會在內存里還是磁盤上完成?!癛ange checked for each record(index map: N)”這個意味著沒有好用的索引,新的索引將在聯接的每一行上重新估算,N是顯示在possible_keys列中索引的位圖,并且是冗余的。
?
七、慢日志查詢
a、配置MySQL自動記錄慢日志
slow_query_log = OFF 是否開啟慢日志記錄 long_query_time = 2 時間限制,超過此時間,則記錄 slow_query_log_file = /usr/slow.log 日志文件 log_queries_not_using_indexes = OFF 未使用索引的搜索是否記錄?
配置:- 在內存中修改查看當前配置信息:show variables like '%query%' 查看慢日志配置
show variables like '%querise%' 查看未使用索引的搜索是否記錄
修改當前配置信息:
set global 變量名 = 值- 在配置文件中修改在終端啟動時輸入命令啟動配置文件mysqld --defaults-file=“配置文件路徑” 創建my.conf配置文件:slow_query_log = ON slow_query_log_file = D:/....注意:修改配置文件之后,先備份,再重啟服務
?
?
?
?
?
轉載于:https://www.cnblogs.com/domestique/p/6994863.html
總結
- 上一篇: halcon边缘检测的方法及各种方法的适
- 下一篇: Linux课堂笔记-第二天