索引的使用前端
首先创建库以后,并建立表,表结构以下: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