索引的使用前端
首先創建庫以後,並建立表,表結構以下:node
mysql> createdatabase test1;mysql
Query OK, 0 rowsaffected (0.01 sec)sql
mysql> use test1;框架
Database changedide
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