MySQL索引简单例子

建表
# index_a表只有主键,无其他索引
mysql> create table index_a (
    -> id int unsigned not null auto_increment,
    -> title varchar(64) not null,
    -> name varchar(16) not null,
    -> stock int not nul default 0,
    -> create_time int not null default 0,
    -> primary key (id)
    -> );
Query OK, 0 rows affected (0.36 sec)
# index_b表有主键和单列索引
mysql> create table  index_b (
    ->     id int unsigned not null auto_increment,
    ->     title varchar(64) not null,
    ->     name varchar(16) not null,
    ->     sn varchar(12) not null default '',
    ->     stock int not null default 0,
    ->     create_time int not null default 0,
    ->     primary key (id),
    ->     unique key name(name) using btree,
    ->     unique key sn(sn) using btree
    -> );
Query OK, 0 rows affected (0.58 sec)
# index_c表有主键和组合索引
mysql> create table  index_c (
    ->     id int unsigned not null auto_increment,
    ->     title varchar(64) not null,
    ->     name varchar(16) not null,
    ->     sn varchar(12) not null default '',
    ->     stock int not null default 0,
    ->     create_time int not null default 0,
    ->     primary key (id),
    ->     KEY name_sn_index(name, sn) using btree
    -> );
Query OK, 0 rows affected (0.48 sec)
PHP脚本插入数据
<?php
// 三个表分别插入100w条数据
set_time_limit(0);
// 断掉连接 后台挂起
// fastcgi_finish_request();

$host = 'localhost';
$db   = 'samp_db';
$user = 'samp';
$pass = 'samp';

$conn = new PDO('mysql:host='.$host.';dbname='.$db, $user, $pass);

$sth = $conn->beginTransaction();

$sql = 'insert into index_a
    (title, name, sn, stock, create_time)
    values (?,?,?,?,?)';  # index_a另外换成index_b index_c
$sth = $conn->prepare($sql);

$time = strtotime('2010-01-01');

echo date('H:i:s') . '<br>';
for ($i = 1; $i < 1000000; $i++) {
    // 设置当前第几个
    $num = substr($i + 1000000, 1, 6);
    // 插入数据
    $sth->execute([
        'title_' . $num,
        'name_' . $num,
        'sn_' . $num,
        rand(1000, 2000),
        $time,
    ]);
    $time += 50;
    // 每1w条提交一次
    if ($i % 10000 == 0) {
        $conn->commit();
        $conn->beginTransaction();
    }
}
$conn->commit();
echo date('H:i:s');
索引简单测试
# 通过指定name分别查询
# a表name无索引
# b表name有单列索引
# c表name有组合索引
mysql> set profiling=1;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from index_a where name='name_876543';
......
mysql> select * from index_b where name='name_876543';
......
mysql> select * from index_c where name='name_876543';
......

mysql> show profiles;
+----------+------------+------------------------------------------------+
| Query_ID | Duration   | Query                                          |
+----------+------------+------------------------------------------------+
|        1 | 1.70158355 | select * from index_a where name='name_876543' |
|        2 | 0.00110591 | select * from index_b where name='name_876543' |
|        3 | 0.02820820 | select * from index_c where name='name_876543' |
+----------+------------+------------------------------------------------+
3 rows in set (0.00 sec)
# 通过title查询
# a b c三表title均无索引
mysql> select * from index_a where title = 'title_456789';
......
mysql> select * from index_b where title = 'title_456789';
......
mysql> select * from index_c where title = 'title_456789';
......

mysql> show profiles;  # 只显示相关
+----------+------------+----------------------------------------------------+
| Query_ID | Duration   | Query                                              |
+----------+------------+----------------------------------------------------+
|        4 | 0.51155937 | select * from index_a where title = 'title_456789' |
|        5 | 0.63892961 | select * from index_b where title = 'title_456789' |
|        6 | 0.54366214 | select * from index_c where title = 'title_456789' |
+----------+------------+----------------------------------------------------+
6 rows in set (0.00 sec)
# 测试like
# a表name无索引
# b表name有单列索引
# c表name有组合索引
mysql> select * from index_a where name like '%www';
......
mysql> select * from index_b where name like '%www';
......
mysql> select * from index_c where name like '%www';
......
mysql> select * from index_a where name like 'www%';
......
mysql> select * from index_b where name like 'www%';
......
mysql> select * from index_c where name like 'www%';
......

mysql> show profiles;
+----------+------------+----------------------------------------------+
| Query_ID | Duration   | Query                                        |
+----------+------------+----------------------------------------------+
|        1 | 3.31670231 | select * from index_a where name like '%www' |
|        2 | 3.24503318 | select * from index_b where name like '%www' |
|        3 | 3.53191539 | select * from index_c where name like '%www' |
|        4 | 3.58034354 | select * from index_a where name like 'www%' |
|        5 | 0.00045643 | select * from index_b where name like 'www%' |
|        6 | 0.00040764 | select * from index_c where name like 'www%' |
+----------+------------+----------------------------------------------+
6 rows in set (0.00 sec)
# 综上: MySQL对于like 'www%'索引有效,对于'%www'索引无效。
# 测试or
# a 无索引
# b name sn都有索引
# c (name, sn) 组合索引
mysql> select * from index_a where name='name_556677' or sn = 'sn_667788';
......
mysql> select * from index_b where name='name_556677' or sn = 'sn_667788';
......
mysql> select * from index_c where name='name_556677' or sn = 'sn_667788';
......

mysql> show profiles;
+----------+------------+--------------------------------------------------------------------+
| Query_ID | Duration   | Query                                                              |
+----------+------------+--------------------------------------------------------------------+
|        1 | 0.59950080 | select * from index_a where name='name_556677' or sn = 'sn_667788' |
|        2 | 0.00161993 | select * from index_b where name='name_556677' or sn = 'sn_667788' |
|        3 | 0.60054383 | select * from index_c where name='name_556677' or sn = 'sn_667788' |
+----------+------------+--------------------------------------------------------------------+
3 rows in set (0.00 sec)
# 综上: or需要条件都加索引才命中[bc表对比,ac表对比]
mysql> select * from index_a where name in ('name_111111', 'name_333333');
......
mysql> select * from index_b where name in ('name_111111', 'name_333333');
......
mysql> select * from index_c where name in ('name_111111', 'name_333333');
......
2 rows in set (0.00 sec)

mysql> show profiles;
+----------+------------+--------------------------------------------------------------------+
| Query_ID | Duration   | Query                                                              |
+----------+------------+--------------------------------------------------------------------+
|        1 | 0.63480784 | select * from index_a where name in ('name_111111', 'name_333333') |
|        2 | 0.00107901 | select * from index_b where name in ('name_111111', 'name_333333') |
|        3 | 0.00122203 | select * from index_c where name in ('name_111111', 'name_333333') |
+----------+------------+--------------------------------------------------------------------+
3 rows in set (0.00 sec)
# 综上: in可以命中索引
# 测试范围符号(>,>=,<,<=,between)
# 先为index_b的stock加上索引
mysql> alter table index_b add index stock(stock);
Query OK, 0 rows affected (5.09 sec)                
Records: 0  Duplicates: 0  Warnings: 0

MariaDB [samp_db]> select count(1) from index_a where stock > 1900;
......
MariaDB [samp_db]> select count(1) from index_b where stock > 1900;
......
MariaDB [samp_db]> select count(1) from index_c where stock > 1900;
......
MariaDB [samp_db]> select count(1) from index_a where stock between 1000 and 1050;
......
MariaDB [samp_db]> select count(1) from index_b where stock between 1000 and 1050;
......
MariaDB [samp_db]> select count(1) from index_c where stock between 1000 and 1050;
......

MariaDB [samp_db]> show profiles;
+----------+------------+----------------------------------------------------------------+
| Query_ID | Duration   | Query                                                          |
+----------+------------+----------------------------------------------------------------+
|        4 | 1.09335718 | select count(1) from index_a where stock > 1900                |
|        5 | 0.05711385 | select count(1) from index_b where stock > 1900                |
|        6 | 0.31060459 | select count(1) from index_c where stock > 1900                |
|        7 | 0.34946092 | select count(1) from index_a where stock between 1000 and 1050 |
|        8 | 0.03301252 | select count(1) from index_b where stock between 1000 and 1050 |
|        9 | 0.31163826 | select count(1) from index_c where stock between 1000 and 1050 |
+----------+------------+----------------------------------------------------------------+
9 rows in set (0.00 sec)
# 通过时间对比,以及explain,比较符,between可以命中索引[不全面]
# 测试and
MariaDB [samp_db]> select * from index_a where name='name_555666' and sn='sn_777888';
......
MariaDB [samp_db]> select * from index_b where name='name_555666' and sn='sn_777888';
......
MariaDB [samp_db]> select * from index_c where name='name_555666' and sn='sn_777888';
......
MariaDB [samp_db]> show profiles;
+----------+------------+-------------------------------------------------------------------+
| Query_ID | Duration   | Query                                                             |
+----------+------------+-------------------------------------------------------------------+
|        1 | 0.61768279 | select * from index_a where name='name_555666' and sn='sn_777888' |
|        2 | 0.00109431 | select * from index_b where name='name_555666' and sn='sn_777888' |
|        3 | 0.00079209 | select * from index_c where name='name_555666' and sn='sn_777888' |
+----------+------------+-------------------------------------------------------------------+
3 rows in set (0.00 sec)
# 综上: 单列以及组合所以可以命中 「最左前缀匹配原则」
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 210,914评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 89,935评论 2 383
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,531评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,309评论 1 282
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,381评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,730评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,882评论 3 404
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,643评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,095评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,448评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,566评论 1 339
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,253评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,829评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,715评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,945评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,248评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,440评论 2 348

推荐阅读更多精彩内容