12.为表的字段创建索引

数据库索引就象书的目录一样,如果在字段上建立了索引,那么以索引列为查询条件时 可以加快查询数据的速度 查询数据库,按主键查询是最快的,每个表只能有一个主键列,但是可以有多个普通索 引列,主键列要求列的所有内容必须唯一,而普通索引列不要求内容必须唯一 主键就类似我们在学校学习时的学号一样,班级里是唯一的,整个表的每一条记录的 键值在表内都是唯一的,用来唯一标识一条记录。

12.1 为表创建主键索引的方法

mysql> use oldboy
Database changed
mysql> create table student(
 -> id int(4) not null AUTO_INCREMENT,
 -> name char(20) not null,
 -> age tinyint(2) not null default '0',
-> dept varchar(16) default null,
->primary key(id),
->KEY index_name(name)
->);​

 

提示:
primary key(id) <-主键
KEY index_name(name) <-name 字段普通索引
只有 int 类型且为 primary key 才可以使用 auto_increment

12.2 查看 student 表的结构

mysql> show create table student\G;
*************************** 1. row ***************************
 Table: student
Create Table: CREATE TABLE `student` (
 `id` int(4) NOT NULL AUTO_INCREMENT,
 `name` char(20) NOT NULL,
 `age` tinyint(2) NOT NULL DEFAULT '0',
 `dept` varchar(16) DEFAULT NULL,
 PRIMARY KEY (`id`),
 KEY `index_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
ERROR:
No query specified
mysql> describe student;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(4) | NO | PRI | NULL | auto_increment |
| name | char(20) | NO | MUL | NULL | |
| age | tinyint(2) | NO | | 0 | |
| dept | varchar(16) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)​

 

12.3 怎么删除一个表的主键

mysql> alter table student drop primary key;​

 

提示:如果一个表中的 primary key 设置了 AUTO_INCREMENT(自动增加)的话,就删不掉

12.4 利用 alter 命令修改 id 列为自增主键列

mysql> alter table student change id id int primary key auto_increment;

 

12.5 建表后利用 alter 增加普通索引

删除建表时创建的 index_name 索引
mysql> select database();
+------------+
| database()
+------------+
| oldboy |
+------------+
1 row in set (0.00 sec)
mysql> show create table student;
+---------+----------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
--------------------------------+
| Table | Create Table
|
+---------+----------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
--------------------------------+
| student | CREATE TABLE `student` (
 `id` int(4) NOT NULL AUTO_INCREMENT,
 `name` char(20) NOT NULL,
 `age` tinyint(2) NOT NULL DEFAULT '0',
 `dept` varchar(16) DEFAULT NULL,
 PRIMARY KEY (`id`),
 KEY `index_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+---------+----------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
--------------------------------+
1 row in set (0.00 sec)
删除普通索引
mysql> alter table student drop index index_name;
Query OK, 0 rows affected (0.08 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show create table student;
+---------+----------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
---+
| Table | Create Table
|
+---------+----------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
---+
| student | CREATE TABLE `student` (
 `id` int(4) NOT NULL AUTO_INCREMENT,
 `name` char(20) NOT NULL,
 `age` tinyint(2) NOT NULL DEFAULT '0',
 `dept` varchar(16) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+---------+----------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
---+
1 row in set (0.00 sec)
创建普通索引
mysql> use oldboy
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> alter table student add index index_name (name);
Query OK, 0 rows affected (0.47 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show create table student;
+---------+----------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
--------------------------------+
| Table | Create Table
|
+---------+----------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
--------------------------------+
| student | CREATE TABLE `student` (
 `id` int(4) NOT NULL AUTO_INCREMENT,
 `name` char(20) NOT NULL,
 `age` tinyint(2) NOT NULL DEFAULT '0',
 `dept` varchar(16) DEFAULT NULL,
 PRIMARY KEY (`id`),
 KEY `index_name` (`name`) 提示:访问数据量很大的时候,不适合建立普通索引,会影响
用户访问,尽量选择业务低估时建立索引
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+---------+----------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
--------------------------------+
1 row in set (0.00 sec)​

 

 12.6 对表字段的前 n 个字符创建普通索引

当遇到表中比较大的列时,列内容的前 n 个字符在所有内容中已接近唯一时,这时可以对列的前 n 个字符建立索引,而无需对整个列建立本索引,这样可以节省创建索引占用的系统空间,以及降低读取和更新维护索引消耗的系统资源。
对字段前 n 个字符创建普通索引的语法:
create index index_name on student(name(8));条件列前 N 个字符创建索引
下面来实战演示:

mysql> select database();
+------------+
| database() |
+------------+
| oldboy |
+------------+
1 row in set (0.00 sec)
为 dept 列前八个字符创建普通索引
mysql> describe student;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(4) | NO | PRI | NULL | auto_increment |
| name | char(20) | NO | MUL | NULL | |
| age | tinyint(2) | NO | | 0 | |
| dept | varchar(16) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
mysql> create index index_name_dept on student (dept(8));
Query OK, 0 rows affected (0.21 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> describe student;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(4) | NO | PRI | NULL | auto_increment |
| name | char(20) | NO | MUL | NULL | |
| age | tinyint(2) | NO | | 0 | |
| dept | varchar(16) | YES | MUL | NULL | |
+-------+-------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
mysql> show create table student;
+---------+----------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------+
| Table | Create Table
|
+---------+----------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------+
| student | CREATE TABLE `student` (
 `id` int(4) NOT NULL AUTO_INCREMENT,
`name` char(20) NOT NULL,
 `age` tinyint(2) NOT NULL DEFAULT '0',
 `dept` varchar(16) DEFAULT NULL,
 PRIMARY KEY (`id`),
 KEY `index_name` (`name`),
 KEY `index_name_dept` (`dept`(8))
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+---------+----------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------+
1 row in set (0.00 sec)​

 

另外一种建立表后创建普通索引的方法:

mysql> alter table student add index index_name_dept (dept(8));​

 

12.7 为表的多个字段创建联合索引

如何查询数据的条件时多列时,我们可以为多个查询的列创建联合索引,甚至,可以为多列的前 n 个字符列创建联合索引,实战演示如下:

mysql> create index index_name_and_dept on student (name,dept);
Query OK, 0 rows affected (0.11 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show create table student;
+---------+----------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------+
| Table | Create Table
|
+---------+----------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------+
| student | CREATE TABLE `student` (
 `id` int(4) NOT NULL AUTO_INCREMENT,
 `name` char(20) NOT NULL,
 `age` tinyint(2) NOT NULL DEFAULT '0',
 `dept` varchar(16) DEFAULT NULL,
 PRIMARY KEY (`id`),
 KEY `index_name` (`name`),
 KEY `index_name_dept` (`dept`(8)),
 KEY `index_name_and_dept` (`name`,`dept`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+---------+----------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)​

 

12.8 为表的多个字段的前 n 个字符创建联合索引

mysql> create index index_name_and_dept on student (name(10),dept(10));
Query OK, 0 rows affected (0.03 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show create table student;
+---------+----------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
----+
| Table | Create Table
|
+---------+----------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
----+
| student | CREATE TABLE `student` (
 `id` int(4) NOT NULL AUTO_INCREMENT,
 `name` char(20) NOT NULL,
 `age` tinyint(2) NOT NULL DEFAULT '0',
 `dept` varchar(16) DEFAULT NULL,
 PRIMARY KEY (`id`),
 KEY `index_name` (`name`),
 KEY `index_name_dept` (`dept`(8)),
 KEY `index_name_and_dept` (`name`(10),`dept`(10))
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+---------+----------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
----+
1 row in set (0.00 sec)​

 

提示:按条件列查询数据时,联合索引是有前缀生效特性的
index(a,b,c)仅 a,ab,abc 三个查询条件列可以走索引,b,bc,ac,c 等无法使用索引了

尽量把最常用作为查询条件的列,放在第一位置

12.9 主键也可以联合多列做索引

*************************** 1. row ***************************
 Table: user
Create Table: CREATE TABLE `user` (
 `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '',
 `User` char(16) COLLATE utf8_bin NOT NULL DEFAULT '',
 `Password` char(41) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL DEFAULT '',
 `Select_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
 `Insert_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
 `Update_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
 `Delete_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
 `Create_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
 `Drop_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
 `Reload_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
 `Shutdown_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
 `Process_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
 `File_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
 `Grant_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
 `References_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
 `Index_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
 `Alter_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
 `Show_db_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
 `Super_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
 `Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
 `Lock_tables_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
 `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
 `Repl_slave_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
 `Repl_client_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
 `Create_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
 `Show_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
 `Create_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
 `Alter_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
 `Create_user_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
 `Event_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
 `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
 `Create_tablespace_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
 `ssl_type` enum('','ANY','X509','SPECIFIED') CHARACTER SET utf8 NOT NULL DEFAULT
'',
 `ssl_cipher` blob NOT NULL,
 `x509_issuer` blob NOT NULL,
 `x509_subject` blob NOT NULL,
 `max_questions` int(11) unsigned NOT NULL DEFAULT '0',
 `max_updates` int(11) unsigned NOT NULL DEFAULT '0',
 `max_connections` int(11) unsigned NOT NULL DEFAULT '0',
 `max_user_connections` int(11) unsigned NOT NULL DEFAULT '0',
 `plugin` char(64) COLLATE utf8_bin DEFAULT '',
 `authentication_string` text COLLATE utf8_bin,
 PRIMARY KEY (`Host`,`User`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Users and
global privileges'
1 row in set (0.00 sec)
ERROR:
No query specified​ 

 

12.10  统计一个字段列的唯一值个数

  1. mysql> select user from mysql.user;
    +-----------+
    | user |
    +-----------+
    | root |
    | blog |
    | oldgirl |
    | wordpress |
    | oldgirl |
    | oldboy |
    | oldgirl |
    | root |
    +-----------+
    8 rows in set (0.00 sec)
    mysql> select count(distinct user) from mysql.user;
    +----------------------+
    | count(distinct user) |
    +----------------------+
    | 5 |
    +----------------------+
    1 row in set (0.06 sec)
    提示:尽量在唯一值多的大表上建立索引​

     

12.11  创建唯一索引(非主键)

mysql> show create table student ;
+---------+----------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
--------------------------------------+
| Table | Create Table
|
+---------+----------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
--------------------------------------+
| student | CREATE TABLE `student` (
`id` int(4) NOT NULL AUTO_INCREMENT,
`name` char(20) NOT NULL,
`age` tinyint(2) NOT NULL DEFAULT '0',
`dept` varchar(16) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `index_age` (`age`),
KEY `index_name` (`name`),
KEY `index_name_dept` (`dept`(8)),
KEY `index_name_and_dept` (`name`(10),`dept`(10))
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+---------+----------------------------------------------------------------------------------------------------------
1 row in set (0.00 sec)​

 

12.12  索引列的创建及生效条件

问题一:既然索引可以加快查询速度,那么就给所有的列建索引吧?
解答:因为索引不但占用系统空间,而且更新数据时还需要维护索引数据的,因此,索引是一把双刃剑,并不是越多越好,例如:数十到几百行的小表上无需建立索引,更新频繁,读取比较少的表要少建立索引
问题二:需要在哪些列上创建索引了?
解答:select user,host from mysql.user where password=...,索引一定要创建在 where 后的条件列上,而不是 select 后的选择数据的列上,另外,我们要尽量选择在唯一值多的大表上的列建立索引,例如:男女性别列唯一值,不适合建立索引

posted @ 2020-03-21 15:39  流氓徐志摩  阅读(1416)  评论(0编辑  收藏  举报