索引的使用
首先建立庫之後,並建立表,表結構如下:
mysql> createdatabase test1;
Query OK, 0 rowsaffected (0.01 sec)
mysql> use test1;
Database changed
mysql> createtable yw (
-> id int unsigned not nullauto_increment,
-> c1 int not null default `0`,
-> c2 int not null default `0`,
-> c3 int not null default `0`,
-> c4 int not null default `0`,
-> c5 timestamp not null,
-> c6 varchar(200) not null default “,
-> primary key(id)
-> );
Query OK, 0 rowsaffected (0.01 sec)
匯入sql檔案
內容如下
[root@mysql_node1test]# cat suoyin_test.sql
drop table yw; #已將剛才建立的庫刪除了,然後又重新建立了一個庫
create table yw (
id int unsigned notnull primary key auto_increment,
c1 int not nulldefault `0`,
c2 int not nulldefault `0`,
c3 int not nulldefault `0`,
c4 int not nulldefault `0`,
c5 timestamp notnull,
c6 varchar(200) notnull default “
);
delimiter $$
drop procedure ifexists `insert_yw` $$
create procedure`insert_yw`(in row_num int )
begin
declare i int default 0;
while i < row_num do
insert into yw(c1, c2, c3,c4, c5,c6) values(floor(rand()*row_num),floor(rand()*row_num),floor(rand()*row_num),floor(rand()*row_num),now(),repeat(`wubx`, floor(rand()*20)));
set i = i+1;
END while;
end$$
delimiter ;
#插入300W條資料
callinsert_yw(3000000);
delimiter $$
drop procedure ifexists `update_yw` $$
create procedure`update_yw`(in row_num int )
begin
declare i int default 0;
while i < row_num do
update yw set c3= floor(rand()*row_num) whereid=i;
set i = i+1;
END while;
end$$
delimiter ;
更改引數
mysql> set globalinnodb_flush_log_at_trx_commit=2
匯入資料表
mysql> source/root/test/suoyin.sql
Query OK, 0 rowsaffected (0.11 sec)
Query OK, 0 rowsaffected (0.01 sec)
Query OK, 0 rowsaffected (0.00 sec)
Query OK, 0 rowsaffected (0.00 sec)
Query OK, 1 row affected(4 min 20.75 sec)
Query OK, 0 rowsaffected (0.00 sec)
Query OK, 0 rowsaffected (0.00 sec)
我們會發現匯入很慢,當然300W條資料也不小,所以我們的問題來了:
為什麼這個查詢這麼慢?
mysql> select *from yw a, (select c2 from yw where id=10) b where a.c2 =b.c2;
+———+———+——–+———+———+———————+——————————————————————+——–+
| id | c1 | c2 | c3 | c4 | c5 | c6 | c2 |
+———+———+——–+———+———+———————+——————————————————————+——–+
| 10 | 2833881 | 185188 | 1424297 | 565924 | 2014-09-24 14:30:31 |wubxwubxwubxwubxwubxwubxwubxwubxwubxwubx | 185188 |
| 1530223 | 1345871 |185188 | 2888330 | 1886085 | 2014-09-24 14:32:44 | wubxwubxwubxwubxwubx |185188 |
| 1623964 | 1289414 |185188 | 57699 | 2732932 | 2014-09-2414:32:52 | wubxwubxwubxwubxwubxwubxwubxwubxwubx | 185188 |
| 2825263 | 729557 | 185188 | 1737273 | 2130798 |2014-09-24 14:34:37 | wubxwubxwubxwubxwubxwubxwubxwubxwubxwubxwubxwubxwubxwubxwubxwubx| 185188 |
+———+———+——–+———+———+———————+——————————————————————+——–+
4 rows in set (7.28 sec)
經過最後檢視,顯示的是7.28秒執行完成,一個很簡單的查詢但是執行完後會很慢,
那麼這裡我們看到一個2825263, 那麼我們將sql改為一個簡單的sql並檢視
這是一個非常簡單的sql,如果在有索引的300w的資料,應該是非常快的,但實際上的表結構跑這樣的sql還是很慢的,如下所示,總共用了7.96秒,如下所示:
mysql> select * from yw where c1 = 2825263 ;
+———+———+———+———+———+———————+——————————————————+
| id | c1 | c2 | c3 | c4 | c5 | c6 |
+———+———+———+———+———+———————+——————————————————+
| 1421241 | 2825263 |2015825 | 1603339 | 1969218 | 2014-09-24 14:32:35 |wubxwubxwubxwubxwubxwubxwubxwubxwubxwubxwubxwubxwubx |
+———+———+———+———+———+———————+——————————————————+
1 row in set (7.96 sec)
之所以慢,是因為在全表掃描而造成的
這種情況下可以對其進行新增索引進行優化
再次追加300萬條資料
使用call insert_表名 進行新增
mysql> call insert_yw(3000000);
Query OK, 1 rowaffected (4 min 21.74 sec)
大概在7分鐘將索引新增將300萬條資料載入完畢
PS:在生產環境中都要模擬百萬條的資料去進行測試
建立完後檢視索引大小,大概476M左右
[root@mysql_node1test1]# ll -th
總用量 477M
-rw-rw—-. 1 mysqlmysql 476M 9月 24 14:49 yw.ibd
-rw-rw—-. 1 mysqlmysql 8.6K 9月 24 14:30 yw.frm
-rw-rw—-. 1 mysqlmysql 61 9月 24 14:00 db.opt
mysql> desc select* from yw a, (select c2 from yw where id=10) b where a.c2 =b.c2;
+—-+————-+————+——–+—————+———+———+——+———+————-+
| id | select_type |table | type | possible_keys | key | key_len | ref | rows | Extra |
+—-+————-+————+——–+—————+———+———+——+———+————-+
| 1 | PRIMARY | <derived2> | system | NULL | NULL | NULL | NULL | 1 | |
| 1 | PRIMARY | a | ALL | NULL | NULL | NULL | NULL | 5936589 | Using where |
| 2 | DERIVED | yw | const | PRIMARY | PRIMARY | 4 | | 1 | |
+—-+————-+————+——–+—————+———+———+——+———+————-+
3 rows in set (0.00sec)
索引的使用
索引的簡介
索引實際上是Btree結構
有些生產環境上尤其是在主從環境下用不到索引的,從而使得主從延遲,當發現從庫延遲,要先去定位是否是從庫上有sql寫入的時間是否沒有用到索引,如果是的話則加索引即可
這類情況在排查主從結構的時候特別多
而delete也是支援索引的,如果不進行索引,那麼也會進行全表掃描
比如在某場景下我們要批量刪除大量資料,通常建議使用工具或儲存過程去分段(批量)刪除資料,比如:
deletefrom tb where addtime&get;xxxx and addtime<xxxx;
使用這樣的語句去按段刪除
通過索引可以讓update selecet delete 都可以實現到加速,但新增索引的話對寫入影響較重
主建是不能去執行update的,生產中是不應該對update做索引的 因為update會將表重新組織一遍並進行btree重排序,所以會非常慢
建立索引,並將其進行對比
將之前建立的表改名並新增新所索引
mysql> renametable yw to yw_1;
ERROR 2006 (HY000):MySQL server has gone away
No connection. Tryingto reconnect…
Connection id: 12
Current database:test1
Query OK, 0 rowsaffected (0.11 sec)
mysql> showtables;
+—————–+
| Tables_in_test1 |
+—————–+
| yw_1 |
+—————–+
1 row in set (0.00sec)
新建表
create table yw (
id int unsigned not null auto_increment,
c1 int not null default `0`,
c2 int not null default `0`,
c3 int not null default `0`,
c4 int not null default `0`,
c5 timestamp not null,
c6 varchar(200) not null default “,
primary key(`id`),
KEY `idx_c2`(`c2`),
key `idx_c3`(`c3`)
);
Query OK, 0 rowsaffected (0.03 sec)
檢視錶結構
mysql> desc yw;
+——-+——————+——+—–+——————-+—————————–+
| Field | Type | Null | Key | Default | Extra |
+——-+——————+——+—–+——————-+—————————–+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| c1 | int(11) | NO | | 0 | |
| c2 | int(11) | NO | MUL | 0 | |
| c3 | int(11) | NO | MUL | 0 | |
| c4 | int(11) | NO | | 0 | |
| c5 | timestamp | NO | | CURRENT_TIMESTAMP | onupdate CURRENT_TIMESTAMP |
| c6 | varchar(200) | NO | | | |
+——-+——————+——+—–+——————-+—————————–+
7 rows in set (0.07sec)
[root@mysql_node1test]# cat 2.sql
delimiter $$
drop procedure ifexists `update_yw` $$
create procedure`update_yw`(in row_num int )
begin
declare i int default 0;
while i < row_numdo
update yw set c3=floor(rand()*row_num) where id=i;
set i = i+1;
END while;
end$$
delimiter ;
匯入
mysql> source/root/test/2.sql
Query OK, 0 rowsaffected (0.00 sec)
Query OK, 0 rowsaffected (0.00 sec)
再次插入300W條記錄,檢視用時時間
mysql> callinsert_yw(3000000);
Query OK, 1 rowaffected (8 min 11.57 sec)
將之前備份的表還原並再次執行,這裡插入一百萬條資料
mysql> renametable yw to yw_idx;
Query OK, 0 rowsaffected (0.06 sec)
mysql> renametable yw_1 to yw;
Query OK, 0 rowsaffected (0.01 sec)
mysql> showtables;
+—————–+
| Tables_in_test1 |
+—————–+
| yw |
| yw_idx |
+—————–+
2 rows in set (0.00sec)
這樣一個是帶索引,一個是不帶索引的
再次呼叫包含索引的結構
mysql> call update_yw(3000000);
Query OK, 1 rowaffected (4 min 32.31 sec)
與之對比如下:
表名 |
是否所用索引 |
執行過程所耗時間 |
yw |
否 |
11.57 sec |
yw_idx |
是 |
32.31 sec |
兩者間速度相差3倍左右
如果存在c3的索引的話,那麼執行以下sql語句:
select c3 from yw where id=1;
發現同樣是很慢的,因為在發生更新第三列的時候同時需要做索引的維護
索引同樣是Btree結構,如果發生任何變更的時候,會將Btree更新,重新排序,這樣就會重新開銷所以會慢
MySQL支援什麼樣的索引?
一般來講都5類
普通索引,唯一索引,主建,組合索引,全文索引(mysql5.6的特性)
全文搜尋第三方工具:sphinx
建立索引:
create index idx_xxx ontb(xxx);
更新索引:
alter table tb add indexidx_xxx(xxx);
刪除索引:
DROP [ONLINE|OFFLINE]INDEX index_name ON tbl_name
普通索引一般包含字首索引,如果前端部分很長可以建立字首索引(前字元區分開來,減少一下索引的長度,讓掃起來更省點IO),如下所示:
alter table yw add indxidx_c6_6(c6(6));
普通索引是的列是可以NULL的
唯一索引:
在設計中屬於一種約束,在使用中,設定欄位唯一的,或者是聯合索引
例:
select * from table_nameidx_xxx=xxx;
如果在普通索引中,在記錄中探測到下下條再判斷是否是需要的記錄,如果是則返回,所以普通索引是要往下多度幾次,這是普通索引的開銷
但唯一索引,只做等於匹配,不會再往下進行,其好處是比較節省IO,
唯一索引列可以允許有NULL,但只能有一個
主建
Innodb裡聚集class index key以為所有的資料以主建排序儲存
主建是不允許有null列的
組合索引(聯合索引):
也被稱為
select * from yw where c4=XXXX order by c3;
使用explain檢視執行效能
mysql> explainselect * from yw_idx where c3=251609 order by c4;
+—-+————-+——–+——+—————+——–+———+——-+——+—————————–+
| id | select_type |table | type | possible_keys | key | key_len | ref | rows |Extra |
+—-+————-+——–+——+—————+——–+———+——-+——+—————————–+
| 1 | SIMPLE | yw_idx | ref | idx_c3 | idx_c3 | 4 | const | 1 | Using where; Using filesort |
+—-+————-+——–+——+—————+——–+———+——-+——+—————————–+
1 row in set (0.03sec)
實際執行sql還是很慢,key_len為4,但是還會很慢,這種sql是忽悠人的,但是實際上possible_keys裡面是沒有東西的,這屬於一種欺騙性的所以需要注意
使用where條件判斷
如果是字首索引如果用到了c3 是否還可以繼續呼叫c4欄位
select * from yw where c3=xxx or c4=xxxx;
select * from yw where c3=xxx union all select * from yw where c4=xxxx;
可以看到是不能呼叫的,因為在這個條件裡面,c3是可以用到的,而c4是不行的,因為c4是全表掃描的,如有一個地方需要全表掃描的話,那麼不管如何都是需要全表掃描,這也是mysql的一個特性
如果是獨立的欄位,將c3和c4獨立出來,則可以使用索引
以下是沒有意義的索引
select count(*) from yw group by c3, c4;
使用兩個欄位獨立索引都被進行呼叫
使用多索引合併
在5.5版本以上可以使用union 進行多索引合併
mysql> select *from yw where c3=xxx union all select * from yw where c4=xxxx;
這樣c3 c4都有索引 ,這樣的話sql是非常快的
如果使用以下sql語句:
mysql> selectcount(*) from yw group by c3, c4;
2999999 rows in set(57.26 sec)
雖然會用到索引,但是還是會全表掃描,因為掃描的IO過大,用到索引意義也不是很大
如果看到結果集超過一萬行,都可以認為這個sql是可以殺掉了
只要結果集超過1萬行(OLTP)環境,都可以認為這個SQL是有問題的
所以,最好控制結果集查詢大小超過500,這樣就可以避免過大全表掃描,避免IO過高
使用limit
如果我們為其後面加入limit 10 來檢視效果
mysql> explainselect count(*) from yw_idx group byc3,c4 order by id limit 10;
+—-+————-+——–+——+—————+——+———+——+———+———————————+
| id | select_type |table | type | possible_keys | key | key_len | ref | rows | Extra |
+—-+————-+——–+——+—————+——+———+——+———+———————————+
| 1 | SIMPLE | yw_idx | ALL | NULL | NULL | NULL | NULL | 3016886 | Using temporary; Usingfilesort |
+—-+————-+——–+——+—————+——+———+——+———+———————————+
1 row in set (0.00sec)
速度並沒有提升,這種sql在生產環境也是較多
覆蓋索引是能夠查到資料
在生產中,一個表的查詢是能夠數過來的,但是非常小的業務系統非常複雜
例:
Create fulltext indexidx_xxx on TbName(xxxx);
select * from tbwhere match(xxxx) against(‘wubx’);
使用索引中注意的事項
首先建立表結構:
mysql> createtable tb_1 (
-> id int unsigned not null auto_increment,
-> c1 varchar(200) default null ,
-> c2 int not null,
-> primary key (id)
-> );
Query OK, 0 rowsaffected (0.06 sec)
插入資料
mysql> insert intotb_1(c1, c2) values(NULL,1),(1,2),(NULL,3);
Query OK, 3 rowsaffected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0
檢視每列的資料量
mysql> selectcount(c1) ,count(*) ,count(1), count(c2),count(id) from tb_1;
+———–+———-+———-+———–+———–+
| count(c1) |count(*) | count(1) | count(c2) | count(id) |
+———–+———-+———-+———–+———–+
| 1 | 3 | 3 | 3 | 3 |
+———–+———-+———-+———–+———–+
1 row in set (0.00sec)
mysql> select *from tb_1;
+—-+——+—-+
| id | c1 | c2 |
+—-+——+—-+
| 1 | NULL | 1 |
| 2 | 1 | 2 |
| 3 | NULL | 3 |
+—-+——+—-+
3 rows in set (0.00sec)
這裡面觀察出,null是不被統計的,而且null在設計欄位裡如果需要的,需要多一個位元組去標示,所以需要多佔用一個標示位
所以我們需要注意的是:
1.索引不會包含有NULL值的列
2.普通索引列可以有NULL
索引的選擇區分度最大:
比如索引的欄位,比如性別男&女 這個值如果在在幾千萬的資料那麼很小,但是在表裡面有列是最大的,則是使用者的ID號:user_id,每個使用者的ID是唯一的,那麼這個列是可以作為索引的,因為是區分度也就是最高的,另外需要使用短索引,如果使用者名稱裡定義的是varchar(32)實際上我們可以用15個就可以標記出來那麼我們可以:
create index idx_username ontable_name (username(15));
查詢中使用like
例:
like “%aaa%” #這種是不能夠用到索引的
idx_c6(c6) where c6 like “av%”;
而 like av% 是能夠用到索引
idx_c6(c6)
where c6 like “av%”
這樣也是可以用到索引的,like語句如果前後百分號是不能用索引的,如果是以字元開頭並以百分號結尾的是可以用到索引的
#如果區分度已經有user_id 這種特別大的列,那麼就沒有必要做其他操作,所以不建議將區分度大的索引與其他索引放在一起,如果放在一起是為了實現索引覆蓋或查詢這種特殊場景,是比較合適的,因為是無法回表
不在列上進行運算
排完序需要取最終的資料,比如oder by 或group by 或select * 之類的sql,索引中沒有包含特殊的資料都是需要回表的
尤其是select * 的語句如果沒有建立全表索引都是要回表的
如下所示:
select * from users where YEAR(adddate)< 2007;
adddate timestamp
這種sql太多是用不到索引的,如果改為基於事件查詢則可以:
(因為2007也是通過引數傳遞進來的)
select * from useradddate <`2007-01-01 00:00:00`;
select * from tbwhere addtime > `2000-01-01 00:00:00` < `2014-XX-XX XX:XX:XX.`;
將其換為小一點的時間這樣意義大一些
差勁的sql案例:
包含不等於,比如id = 1;
select * from ywwhere id!=1;
表示如果不等於1的id 其他全部列印出來。
mysql>explain select * from yw_idx whereid!=1;
+—-+————-+——–+——-+—————+———+———+——+———+————-+
| id | select_type |table | type | possible_keys | key | key_len | ref | rows | Extra |
+—-+————-+——–+——-+—————+———+———+——+———+————-+
| 1 | SIMPLE | yw_idx | range | PRIMARY | PRIMARY | 4 | NULL | 1508444| Using where |
+—-+————-+——–+——-+—————+———+———+——+———+————-+
1 row in set (0.08sec)
這樣的話相當於一次全表掃描
從掃描的行數來看,優化器explain中有rows欄位
從row列表中,可看到接近全表的操作
這裡還有一個情況,我們使用limit並檢視效果
mysql> select *from yw where id!=1 limit 1;
+—-+———+——–+———+——–+———————+————–+
| id | c1 | c2 | c3 | c4 | c5 | c6 |
+—-+———+——–+———+——–+———————+————–+
| 2 | 2333997 | 269341 | 2459005 | 915557 |2014-09-24 15:38:29 | wubxwubxwubx |
+—-+———+——–+———+——–+———————+————–+
1 row in set (0.00sec)
select * from ywwhere id!=1;
select * from ywwhere id!=1 limit 1;
以上兩者可以對比
看起來沒有變化還是這麼多行,但是在limit執行的時候會有流式化的輸出,每當讀取到一行的時候會放入到buffer池中,存到一定數量後會對其進行一次排序,如當已滿足條件了,則不會再進行匹配
但是如果limit之後,速度會快很多,雖然看到此情況,可能會用到索引了,這也是用索引的一種場景
使用not in
not in的主要作用是在執行sql查詢語句的時候不在哪一個資料範圍的的記錄
mysql> select *from yw_idx where c2 not in(4262384,3605632);
mysql> explainselect * from yw_idx where c2 not in(4262384,3605632);
+—-+————-+——–+——+—————+——+———+——+———+————-+
| id | select_type |table | type | possible_keys | key | key_len | ref | rows | Extra |
+—-+————-+——–+——+—————+——+———+——+———+————-+
| 1 | SIMPLE | yw_idx | ALL | idx_c2 | NULL | NULL | NULL | 3016886 | Using where |
+—-+————-+——–+——+—————+——+———+——+———+————-+
1 row in set (0.10sec)
對其優化:
一般來說不能直接使用not in之類的sql語句,這屬於病態sql
優化的時候可以加一個LIMIT,以減少IO
另外limit結果較大的話或者對其結果不滿意的話,可以改為使用left join,然後用主建去關聯id為b 而b.id 為null,如下所示:
mysql> select *from yw a left join ( select id from yw where c2 in (4262384, 3605632)) b ona.id=b.id where b.id is null limit 10;
+—-+———+———+———+———+———————+——————————————————+——+
| id | c1 | c2 | c3 | c4 | c5 | c6 | id |
+—-+———+———+———+———+———————+——————————————————+——+
| 1 | 463681 | 1098981 | 1817518 | 2222359 | 2014-09-24 15:38:29 |wubxwubxwubxwubxwubxwubxwubxwubxwubxwubxwubxwubx | NULL |
| 2 | 2333997 | 269341 | 2459005 | 915557 |2014-09-24 15:38:29 | wubxwubxwubx | NULL|
| 3 | 2971523 | 1226698 | 842469 | 414525 | 2014-09-24 15:38:29 | wubxwubxwubxwubxwubxwubxwubxwubxwubx | NULL |
| 4 | 2835700 | 930937 | 2835332 | 1945110 | 2014-09-24 15:38:29 | wubx | NULL |
| 5 | 1578655 | 1044887 | 2649255 | 2307696 |2014-09-24 15:38:29 | wubxwubxwubxwubxwubxwubxwubx | NULL |
| 6 | 1442242 | 992011 | 1740281 | 190626 |2014-09-24 15:38:29 | wubxwubxwubxwubxwubxwubxwubxwubxwubxwubxwubxwubxwubx |NULL |
| 7 | 693798 | 309586 | 753637 | 2403923 | 2014-09-24 15:38:29 |wubxwubxwubxwubxwubxwubxwubxwubxwubxwubx | NULL |
| 8 | 888272 | 2581335 | 1547343 | 1465295 | 2014-09-24 15:38:29 |wubxwubxwubxwubx | NULL |
| 9 | 1608599 | 240304 | 2475805 | 2157717 | 2014-09-24 15:38:29 | wubxwubxwubxwubx | NULL |
| 10 | 2833881 | 185188 | 1736996 | 565924 | 2014-09-24 15:38:29 |wubxwubxwubxwubxwubxwubxwubxwubxwubxwubx | NULL |
+—-+———+———+———+———+———————+——————————————————+——+
10 rows in set (17.04sec)
改為順序IO
另外一種情況就是將其改為順序IO去取前幾行
只oder by id 將結果只取前10行,如果發現前10行已經能夠滿足需求的話,則將其取出不再做其他操作
mysql> select *from yw where c2 not in(4262384,3605632) order by id limit 10;
+—-+———+———+———+———+———————+——————————————————+
| id | c1 | c2 | c3 | c4 | c5 | c6 |
+—-+———+———+———+———+———————+——————————————————+
| 1 | 463681 | 1098981 | 1817518 | 2222359 | 2014-09-24 15:38:29 |wubxwubxwubxwubxwubxwubxwubxwubxwubxwubxwubxwubx |
| 2 | 2333997 | 269341 | 2459005 | 915557 |2014-09-24 15:38:29 | wubxwubxwubx |
| 3 | 2971523 | 1226698 | 842469 | 414525 | 2014-09-24 15:38:29 | wubxwubxwubxwubxwubxwubxwubxwubxwubx |
| 4 | 2835700 | 930937 | 2835332 | 1945110 | 2014-09-24 15:38:29 | wubx |
| 5 | 1578655 | 1044887 | 2649255 | 2307696 |2014-09-24 15:38:29 | wubxwubxwubxwubxwubxwubxwubx |
| 6 | 1442242 | 992011 | 1740281 | 190626 |2014-09-24 15:38:29 | wubxwubxwubxwubxwubxwubxwubxwubxwubxwubxwubxwubxwubx |
| 7 | 693798 | 309586 | 753637 | 2403923 | 2014-09-24 15:38:29 |wubxwubxwubxwubxwubxwubxwubxwubxwubxwubx |
| 8 | 888272 | 2581335 | 1547343 | 1465295 | 2014-09-24 15:38:29 |wubxwubxwubxwubx |
| 9 | 1608599 | 240304 | 2475805 | 2157717 | 2014-09-24 15:38:29 | wubxwubxwubxwubx |
| 10 | 2833881 | 185188 | 1736996 | 565924 | 2014-09-24 15:38:29 |wubxwubxwubxwubxwubxwubxwubxwubxwubxwubx |
+—-+———+———+———+———+———————+——————————————————+
10 rows in set (0.02sec)
只將結果集比較大的將其追加limit ,再去想辦法對其優化
select * from yw a where a.id not in (select id from yw where id<100000) limit 100;
select * from yw a left join (select id from yw where id<100000) b where a.id = b.id and b.id is null limit 100;
總結
MySQL支援什麼樣的索引以及這幾種索引的區別是什麼
MySQL支援 普通索引、組合索引、唯一索引、主鍵、全文索引、字首索引(隸屬於普通索引)
唯一索引:涉及到約束,包括在讀的時間不會往下去讀的
主建在innodb中作為一個聚集建所存在
短索引:短索引就是字首索引,包含在普通索引中
當一個表裡有一個int索引,varchar索引, 一個查詢會麼用到那個索引?(是先用int索引還是varchar索引呢?)
涉及到索引查詢成本的理解
例:
select * from tbwhere c1_int=xxx and c2_varchar=xxx;
同樣存在idx_c1和idx_c2
假設來講: 總體查詢成本是1, 基於int查詢0.6 基於varchar 是0.7
實際來說基於varchar的是0.7那麼,對於mysql來講是選擇任何一個索引;
如果查詢成本1,那麼其他兩個都小於查詢成本,那麼都是可以的;
那麼這時我們到底選擇哪個完全取決於mysql的機制,mysql是按照先後的順序進行選取
比如
create index varchar
首先建立varchar,那麼,它會選擇varchar,以此類推
所以,是根據其順序進行選擇的,也是mysql的機制
對其核心優化整體框架
核心概念: 減少IO
實際行動: 控制結果集大小,爭取1秒內完成
減少IO, 考慮是否使用順序IO