【数据库】mysql数据库索引

文章归属:http://feiyan.info/16.html,我想自己去写了,但是发现此君总结的非常详细。直接搬过来了

关于MySQL索引的好处,如果正确合理设计并且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索引的MySQL就是一个人力三轮车。对于
没有索引的表,单表查询可能几十万数据就是瓶颈,而通常大型网站单日就可能会产生几十万甚至几百万的数据,没有索引查询会变的非常缓慢。还是以
WordPress来说,其多个数据表都会对经常被查询的字段添加索引,比如wp_comments表中针对5个字段设计了BTREE索引。

一个简单的对比测试

以我去年测试的数据作为一个简单示例,20多条数据源随机生成200万条数据,平均每条数据源都重复大概10万次,表结构比较简单,仅包含一个自增ID,一个char类型,一个text类型和一个int类型,单表2G大小,使用MyIASM引擎。开始测试未添加任何索引。

执行下面的SQL语句:

mysql> SELECT id,FROM_UNIXTIME(time) FROM article WHERE a.title='测试标题'

View Code

查询需要的时间非常恐怖的,如果加上联合查询和其他一些约束条件,数据库会疯狂的消耗内存,并且会影响前端程序的执行。这时给title字段添加一个BTREE索引:

mysql> ALTER TABLE article ADD INDEX index_article_title ON title(200);

View Code

再次执行上述查询语句,其对比非常明显:

MySQL索引的概念

索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针。更通俗的说,数据库索引好比是一
本书前面的目录,能加快数据库的查询速度。上述SQL语句,在没有索引的情况下,数据库会遍历全部200条数据后选择符合条件的;而有了相应的索引之后,
数据库会直接在索引中查找符合条件的选项。如果我们把SQL语句换成“SELECT * FROM article WHERE
id=2000000”,那么你是希望数据库按照顺序读取完200万行数据以后给你结果还是直接在索引中定位呢?上面的两个图片鲜明的用时对比已经给出了
答案(注:一般数据库默认都会为主键生成索引)。

索引分为聚簇索引和非聚簇索引两种,聚簇索引是按照数据存放的物理位置为顺序的,而非聚簇索引就不一样了;聚簇索引能提高多行检索的速度,而非聚簇索引对于单行的检索很快。

MySQL索引的类型

1. 普通索引

这是最基本的索引,它没有任何限制,比如上文中为title字段创建的索引就是一个普通索引,MyIASM中默认的BTREE类型的索引,也是我们大多数情况下用到的索引。

–直接创建索引
CREATE INDEX index_name ON table(column(length))
–修改表结构的方式添加索引
ALTER TABLE table_name ADD INDEX index_name ON (column(length))
–创建表的时候同时创建索引
CREATE TABLE `table` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`title` char(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
`content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL ,
`time` int(10) NULL DEFAULT NULL ,
PRIMARY KEY (`id`),
INDEX index_name (title(length))
)
–删除索引
DROP INDEX index_name ON table

View Code

2. 唯一索引

与普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值(注意和主键不同)。如果是组合索引,则列值的组合必须唯一,创建方法和普通索引类似。

–创建唯一索引
CREATE UNIQUE INDEX indexName ON table(column(length))
–修改表结构
ALTER TABLE table_name ADD UNIQUE indexName ON (column(length))
–创建表的时候直接指定
CREATE TABLE `table` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`title` char(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
`content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL ,
`time` int(10) NULL DEFAULT NULL ,
PRIMARY KEY (`id`),
UNIQUE indexName (title(length))
);

View Code

3. 全文索引(FULLTEXT)

MySQL从3.23.23版开始支持全文索引和全文检索,FULLTEXT索引仅可用于 MyISAM 表;他们可以从CHAR、VARCHAR或TEXT列中作为CREATE TABLE语句的一部分被创建,或是随后使用ALTER TABLE 或CREATE INDEX被添加。////对于较大的数据集,将你的资料输入一个没有FULLTEXT索引的表中,然后创建索引,其速度比把资料输入现有 FULLTEXT索引的速度更为快。不过切记对于大容量的数据表,生成全文索引是一个非常消耗时间非常消耗硬盘空间的做法。

–创建表的适合添加全文索引
    CREATE TABLE `table` (
    `id` int(11) NOT NULL AUTO_INCREMENT ,
    `title` char(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
    `content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL ,
    `time` int(10) NULL DEFAULT NULL ,
    PRIMARY KEY (`id`),
    FULLTEXT (content)
    );
    –修改表结构添加全文索引
    ALTER TABLE article ADD FULLTEXT index_content(content)
    –直接创建索引
    CREATE FULLTEXT INDEX index_content ON article(content)

View Code

4. 单列索引、多列索引

多个单列索引与单个多列索引的查询效果不同,因为执行查询时,MySQL只能使用一个索引,会从多个索引中选择一个限制最为严格的索引。

5. 组合索引(最左前缀)

平时用的SQL查询语句一般都有比较多的限制条件,所以为了进一步榨取MySQL的效率,就要考虑建立组合索引。例如上表中针对title和time建立 一个组合索引:ALTER TABLE article ADD INDEX index_titme_time (title(50),time(10))。建立这样的组合索引,其实是相当于分别建立了下面两组组合索引:

–title,time

–title

为什么没有time这样的组合索引呢?这是因为MySQL组合索引“最左前缀”的结果。简单的理解就是只从最左面的开始组合。并不是只要包含这两列的查询都会用到该组合索引,如下面的几个SQL所示:

–使用到上面的索引
    SELECT * FROM article WHREE title='测试' AND time=1234567890;
    SELECT * FROM article WHREE utitle='测试';
    –不使用上面的索引
    SELECT * FROM article WHREE time=1234567890;

View Code

MySQL索引的优化

上面都在说使用索引的好处,但过多的使用索引将会造成滥用。因此索引也会有它的缺点:虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行 INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。建立索引会占用磁盘空间的索引文件。一般情 况这个问题不太严重,但如果你在一个大表上创建了多种组合索引,索引文件的会膨胀很快。索引只是提高效率的一个因素,如果你的MySQL有大数据量的表, 就需要花时间研究建立最优秀的索引,或优化查询语句。下面是一些总结以及收藏的MySQL索引的注意事项和优化方法。

1. 何时使用聚集索引或非聚集索引?

 

动作描述 使用聚集索引 使用非聚集索引
列经常被分组排序 使用 使用
返回某范围内的数据 使用 不使用
一个或极少不同值 不使用 不使用
小数目的不同值 使用 不使用
大数目的不同值 不使用 使用
频繁更新的列 不使用 使用
外键列 使用 使用
主键列 使用 使用
频繁修改索引列 不使用 使用

 事实上,我们可以通过前面聚集索引和非聚集索引的定义的例子来理解上表。如:返回某范围内的数据一项。比如您的某个表有一个时间列,恰好您把聚合索引建立 在了该列,这时您查询2004年1月1日至2004年10月1日之间的全部数据时,这个速度就将是很快的,因为您的这本字典正文是按日期进行排序的,聚类 索引只需要找到要检索的所有数据中的开头和结尾数据即可;而不像非聚集索引,必须先查到目录中查到每一项数据对应的页码,然后再根据页码查到具体内容。其 实这个具体用法我还不是很理解,只能等待后期的项目开发中慢慢学学了。

 

2. 索引不会包含有NULL值的列

 

只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为NULL。

 

3. 使用短索引

 

对串列进行索引,如果可能应该指定一个前缀长度。例如,如果有一个CHAR(255)的列,如果在前10个或20个字符内,多数值是惟一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。

 

4. 索引列排序

 

MySQL查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序,如果需要最好给这些列创建复合索引。

 

5. like语句操作

 

一般情况下不鼓励使用like操作,如果非使用不可,如何使用也是一个问题。like “%aaa%” 不会使用索引而like “aaa%”可以使用索引。

 

6. 不要在列上进行运算

 

例如:select * from users where YEAR(adddate)<2007,将在每个行上进行运算,这将导致索引失效而进行全表扫描,因此我们可以改成:select * from users where adddate<’2007-01-01′。关于这一点可以围观:一个单引号引发的MYSQL性能损失。

 

最后总结一下,MySQL只对一下操作符才使用索引:<,<=,=,>,>=,between,in,以及某些时候的 like(不以通配符%或_开头的情形)。而理论上每张表里面最多可创建16个索引,不过除非是数据量真的很多,否则过多的使用索引也不是那么好玩的,比 如我刚才针对text类型的字段创建索引的时候,系统差点就卡死了。

 

 

 

 

时间: 2024-11-21 00:35:51

【数据库】mysql数据库索引的相关文章

[数据库]MySQL Hash索引和B-Tree索引的区别

MySQL Hash索引和B-Tree索引的区别究竟在哪里呢?相信很多人都有这样的疑问,下文对两者的区别进行了详细的分析,供您参考. MySQL Hash索引结构的特殊性,其检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问,所以 Hash 索引的查询效率要远高于 B-Tree 索引.  可 能很多人又有疑问了,既然 Hash 索引的效率要比 B-Tree 高很多,为什么大家不都用 Hash 索引而还要使用 B-Tree 索

mysql 数据库-mysql数据库数据量太多有没有必要分开存放?

问题描述 mysql数据库数据量太多有没有必要分开存放? 就是做一个考勤系统,比如很多公司都是用一个考勤系统的后台(java做的后台),那么数据库也是同一个数据库,只是在存取数据时用每个公司有编号区分,这样的话,时间长了会产生很多数据,这样会不会影响访问效率?应该怎么设计数据库?是不是 应该分开存放?每个公司建一个数据库存啊?有没有好的建议?(目前数据库是mysql) 解决方案 这个你需要预估一下数据量,才好判断.如果数据量不大的话,共用一个库也未尝不可.本身考勤系统,就不是大数据量,高并发的系

mysql 数据库-MySQL数据库中有个叫“mysql”的数据库?

问题描述 MySQL数据库中有个叫"mysql"的数据库? 默认就有,而且不能删除?这是什么意思?为什么会有它? 解决方案 这个不能删除,mysql库是系统库,里面保存有账户信息,权限信息,存储过程,event,时区等信息. 解决方案二: 也不是不能删除,选择删除的时候,删除提醒会和一般的数据库不一样 解决方案三: mysql统计数据库中有多少条数据 解决方案四: 系统库,最好不要删掉的.

php通过PHPExcel导入Excel表格到MySQL数据库的简单实例_php实例

如下所示: <?php define('BASE_URL', realpath(dirname(__FILE__))); require_once BASE_URL . '/PHPExcel/PHPExcel.php';//引入PHPExcel类文件 //excel文件的地址 $excel_fiel_path = './phpexcel.xls'; $PHPExcel = new PHPExcel();// 实例化PHPExcel工具类 //分析文件获取后缀判断是2007版本还是2003 $ex

MySQL数据库备份(转)

mysql|备份|数据|数据库 MySQL数据库备份[晏子]  http://clyan.hongnet.com/index.html在数据库表丢失或损坏的情况下,备份你的数据库是很重要的.如果发生系统崩溃,你肯定想能够将你的表尽可能丢失最少的数据恢复到崩溃发生时的状态.有时,正是MySQL管理员造成破坏.管理员已经知道表以破坏,用诸如vi或Emacs等编辑器试图直接编辑它们,这对表绝对不是件好事!备份数据库两个主要方法是用mysqldump程序或直接拷贝数据库文件(如用cp.cpio或tar等

用MySQL创建数据库和数据库表

mysql|创建|数据|数据库     了解了一些最基本的操作命令后,我们再来学习如何创建一个数据库和数据库表. 1.使用SHOW语句找出在服务器上当前存在什么数据库: mysql> SHOW DATABASES; +----------+ | Database | +----------+ | mysql | | test | +----------+ 3 rows in set (0.00 sec) 2.创建一个数据库abccs mysql> CREATE DATABASE abccs;

MYSQL数据库入门

mysql|数据|数据库 MYSQL数据库入门 MySQL简介 什么是MySQL? MySQL是一个多用户.多线程的SQL数据库,是一个客户机/服务器结构的应用,它由一个服务器守护程序mysqld和很多不同的客户程序和库组成. SQL (Structured Query Language结构化查询语言)是目前使用最广的并且是标准的数据库语言.SQL语言使得存取或更新信息变得十分容易,你可以直接使用SQL从网站上查询信息.MySQL的快速和灵活性足以满足一个网站的信息管理工

ASP如何使用MYSQL数据库?

mysql|数据|数据库 MYSQL数据库以它短小.方便.速度快.免费等优点成为很多网站目前首选数据库,但一般都是用PHP+MYSQL相结合来开发各种动态页面,其实ASP也可以使用MYSQL数据库开发动态页面,小弟我也是刚刚学会,不敢独享,所以特写了这篇文章供大伙参考.我的环境是WINDOWS98+PWS4.0+mysql-3.23.32-win+PHP4必要的软件:PWS4.0(呵呵,废话)mysql-3.23.32-win(这个是最新版的)myodbc-2.50.36-dll(这个是最重要的

Linux Shell脚本之利用mysqldump备份MySQL数据库(详细注解)

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://dgd2010.blog.51cto.com/1539422/1678653 设计该脚本的一些设计.编写考虑: 该脚本适用于编译安装mysql和通过yum或apt-get等安装方式 该脚本可以反复执行,不会重复覆盖数据 可增加,删除N天前的备份以节省磁盘空间 充分利用mysqldump的自带锁表功能.刷新日志.复制等功能 利用mysqldump命令备份MySQL数据库的脚本(不带

Linux中更改转移mysql数据库目录的步骤_Mysql

本文是简单整理一下这几天把MySQL从/var/lib/mysql目录下面转移到/home/mysql_data/mysql下面具体操作. 首先我们需要关闭MySQL,命令如下: #service mysqld stop 网上有很多人都是用的mysqladmin -u root -p shutdown,不过我这个是系统安装的是kloxo面板,root密码并不知道,虽然可以重置,但是比较麻烦. 然后是转移数据,为了安全期间,我们采用复制的命令cp,先找到mysql的原目录 #cd /var/lib