视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
添加mysql索引的3条原则_MySQL
2020-11-09 17:27:28 责编:小采
文档


  一,索引的重要性

  索引用于快速找出在某个列中有一特定值的行。不使用索引,MySQL必须从第1条记录开始然后读完整个表直到找出相关的行。表越大,花费的时间越多。如果表中查询的列有一个索引,MySQL能快速到达一个位置去搜寻到数据文件的中间,没有必要看所有数据。注意如果你需要访问大部分行,顺序读取要快得多,因为此时我们避免磁盘搜索。

  假如你用新华字典来查找“张”这个汉字,不使用目录的话,你可能要从新华字典的第一页找到最后一页,可能要花二个小时。字典越厚呢,你花的时间就越多。现在你使用目录来查找“张”这个汉字,张的首字母是z,z开头的汉字从900多页开始,有了这条线索,你查找一个汉字可能只要一分钟,由此可见索引的重要性。但是索引建的是不是越多越好呢,当然不是,如果一本书的目录分成好几级的话,我想你也会晕的。

  二,准备工作

  1. //准备二张测试表
  2. mysql> CREATE TABLE `test_t` (
  3. -> `id` int(11) NOT NULL auto_increment,
  4. -> `num` int(11) NOT NULL default '0',
  5. -> `d_num` varchar(30) NOT NULL default '0',
  6. -> PRIMARY KEY (`id`)
  7. -> ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
  8. Query OK, 0 rows affected (0.05 sec)
  9. mysql> CREATE TABLE `test_test` (
  10. -> `id` int(11) NOT NULL auto_increment,
  11. -> `num` int(11) NOT NULL default '0',
  12. -> PRIMARY KEY (`id`)
  13. -> ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
  14. Query OK, 0 rows affected (0.05 sec)
  15. //创建一个存储过程,为插数据方便
  16. mysql> delimiter |
  17. mysql> create procedure i_test(pa int(11),tab varchar(30))
  18. -> begin
  19. -> declare max_num int(11) default 100000;
  20. -> declare i int default 0;
  21. -> declare rand_num int;
  22. -> declare double_num char;
  23. ->
  24. -> if tab != 'test_test' then
  25. -> select count(id) into max_num from test_t;
  26. -> while i < pa do
  27. -> if max_num < 100000 then
  28. -> select cast(rand()*100 as unsigned) into rand_num;
  29. -> select concat(rand_num,rand_num) into double_num;
  30. -> insert into test_t(num,d_num)values(rand_num,double_num);
  31. -> end if;
  32. -> set i = i +1;
  33. -> end while;
  34. -> else
  35. -> select count(id) into max_num from test_test;
  36. -> while i < pa do
  37. -> if max_num < 100000 then
  38. -> select cast(rand()*100 as unsigned) into rand_num;
  39. -> insert into test_test(num)values(rand_num);
  40. -> end if;
  41. -> set i = i +1;
  42. -> end while;
  43. -> end if;
  44. -> end|
  45. Query OK, 0 rows affected (0.00 sec)
  46. mysql> delimiter ;
  47. mysql> show variables like "%pro%"; //查看一下,记录执行的profiling是不是开启动了,默认是不开启的
  48. +---------------------------+-------+
  49. | Variable_name | Value |
  50. +---------------------------+-------+
  51. | profiling | OFF |
  52. | profiling_history_size | 15 |
  53. | protocol_version | 10 |
  54. | slave_compressed_protocol | OFF |
  55. +---------------------------+-------+
  56. 4 rows in set (0.00 sec)
  57. mysql> set profiling=1; //开启后,是为了对比加了索引后的执行时间
  58. Query OK, 0 rows affected (0.00 sec)

  三,实例

  1,单表数据太少,索引反而会影响速度

  1. mysql> call i_test(10,'test_t'); //向test_t表插入10条件
  2. Query OK, 1 row affected (0.02 sec)
  3. mysql> select num from test_t where num!=0;
  4. mysql> explain select num from test_t where num!=0/G;
  5. *************************** 1. row ***************************
  6. id: 1
  7. select_type: SIMPLE
  8. table: test_t
  9. type: ALL
  10. possible_keys: NULL
  11. key: NULL
  12. key_len: NULL
  13. ref: NULL
  14. rows: 10
  15. Extra: Using where
  16. 1 row in set (0.00 sec)
  17. ERROR:
  18. No query specified
  19. mysql> create index num_2 on test_t (num);
  20. Query OK, 10 rows affected (0.19 sec)
  21. Records: 10 Duplicates: 0 Warnings: 0
  22. mysql> select num from test_t where num!=0;
  23. mysql> explain select num from test_t where num!=0/G;
  24. *************************** 1. row ***************************
  25. id: 1
  26. select_type: SIMPLE
  27. table: test_t
  28. type: index
  29. possible_keys: num_2
  30. key: num_2
  31. key_len: 4
  32. ref: NULL
  33. rows: 10
  34. Extra: Using where; Using index
  35. 1 row in set (0.00 sec)
  36. ERROR:
  37. No query specified
  38. mysql> show profiles;
  39. +----------+------------+---------------------------------------------+
  40. | Query_ID | Duration | Query |
  41. +----------+------------+---------------------------------------------+
  42. | 1 | 0.00286325 | call i_test(10,'test_t') | //插入十条数据
  43. | 2 | 0.00026350 | select num from test_t where num!=0 |
  44. | 3 | 0.00022250 | explain select num from test_t where num!=0 |
  45. | 4 | 0.18385400 | create index num_2 on test_t (num) | //创建索引
  46. | 5 | 0.00127525 | select num from test_t where num!=0 | //使用索引后,差不多是没有使用索引的0.2倍
  47. | 6 | 0.00024375 | explain select num from test_t where num!=0 |
  48. +----------+------------+---------------------------------------------+
  49. 6 rows in set (0.00 sec)

  解释:

  id:表示sql执行的顺序

  select_type:SIMPLE,PRIMARY,UNION,DEPENDENT UNION,UNION RESULT,SUBQUERY,DEPENDENT SUBQUERY,DERIVED不同的查询语句会有不同的select_type

  table:表示查找的表名

  type:表示使用索引类型,或者有无使用索引.效率从高到低const、eq_reg、ref、range、index和ALL,其实这个根你sql的写法有直接关系,例如:能用主键就用主键,where后面的条件加上索引,如果是唯一加上唯一索引等

  possible_keys:可能存在的索引

  key:使用索引

  key_len:使用索引的长度

  ref:使用哪个列或常数与key一起从表中选择行,一般在多表联合查询时会有。

  rows:查找出的行数

  Extra:额外说明

  前段时间写过一篇博文mysql distinct和group by谁更好,里面有朋友留言,说测试结果根我当时做的测试结果不一样,当时我打比方解释了一下,今天有时间,以例子的形势,更直观的表达出索引的工作原理。

  2,where后的条件,order by ,group by 等这样过滤时,后面的字段最好加上索引。根据实际情况,选择PRIMARY KEY、UNIQUE、INDEX等索引,但是不是越多越好,要适度。

  3,联合查询,子查询等多表操作时关连字段要加索引

  1. mysql> call i_test(10,'test_test'); //向test_test表插入10条数据
  2. Query OK, 1 row affected (0.02 sec)
  3. mysql> explain select a.num as num1,b.num as num2 from test_t as a left join tes
  4. t_test as b on a.num=b.num/G;
  5. *************************** 1. row ***************************
  6. id: 1
  7. select_type: SIMPLE
  8. table: a
  9. type: index
  10. possible_keys: NULL
  11. key: num_2
  12. key_len: 4
  13. ref: NULL
  14. rows: 10
  15. Extra: Using index
  16. *************************** 2. row ***************************
  17. id: 1
  18. select_type: SIMPLE
  19. table: b
  20. type: ref
  21. possible_keys: num_1
  22. key: num_1
  23. key_len: 4
  24. ref: bak_test.a.num //bak_test是数据库名,a.num是test_t的一个字段
  25. rows: 1080
  26. Extra: Using index
  27. 2 rows in set (0.01 sec)
  28. ERROR:
  29. No query specified

  数据量特别大的时候,最好不要用联合查询,即使你做了索引。

  上面只是个人的一点小结,抛砖引玉一下。

下载本文
显示全文
专题