mysql索引使用场景(MySQL如何使用索引 较为详细的分析和例子_MySQL)

本文目录
- MySQL如何使用索引 较为详细的分析和例子_MySQL
- MySQL索引的缺点以及MySQL索引在实际操作中有哪些事项
- mysql 主键索引,联合索引,单列索引使用场景
- MySQL索引什么情况下创建
- mysql数据库中的索引有那些、有什么用_MySQL
- Mysql几种索引类型的区别及适用情况
- mysql索引的应用场景以及如何使用
- 数据库基础:讲解MySQL索引的概念及数据库索引的应用[2]
- MySQL怎么使用索引
MySQL如何使用索引 较为详细的分析和例子_MySQL
在数据库表中,使用索引可以大大提高查询速度。假如我们创建了一个 testIndex表:
CREATE TABLE testIndex(i_testID INT NOT NULL,vc_Name VARCHAR(16) NOTNULL);
我们随机向里面插入了 1000条记录,其中有一条 i_testID vc_Name 555 erquan
在查找 vc_Name="erquan"的记录 SELECT *FROM testIndex WHERE vc_Name=’erquan’; 时,如果在vc_Name 上已经建立了索引,MySql 无须任何扫描,即准确可找到该记录!相反,MySql 会扫描所有记录,即要查询 1000。以索引将查询速度提高 100 倍。
一、索引分单列索引和组合索引
单列索引:即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。组合索引:即一个索包含多个列。
二、介绍一下索引的类型
1、普通索引。
这是最基本的索引,它没有任何限制。它有以下几种创建方式:
(1)创建索引:CREATE INDEX indexName ONtableName(tableColumns(length));如果是CHAR,VARCHAR类型,length可以小于字段实际长度;如果是 BLOB 和 TEXT 类型,必须指定 length,下同。
(2)修改表结构:ALTER tableName ADD INDEX ON (tableColumns(length))
(3)创建表的时候直接指定:CREATE TABLE tableName ( (tableColumns(length)) ;
2、唯一索引。
它与前面的"普通索引"类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。它有以下几种创建方式:
(1)创建索引:CREATE UNIQUE INDEX indexName ONtableName(tableColumns(length))
(2)修改表结构:ALTER tableName ADD UNIQUE ON (tableColumns(length))
(3)创建表的时候直接指定:CREATE TABLE tableName ( (tableColumns(length));
3、主键索引
它是一种特殊的唯一索引,不允许有空值。一般是在建表的时候同时创建主键索引:CREATE TABLE testIndex(i_testID INT NOT NULL AUTO_INCREMENT,vc_NameVARCHAR(16) NOT NULL,PRIMARY KEY(i_testID));当然也可以用ALTER 命令。记住:一个表只能有一个主键。
4、全文索引
MySQL从 3.23.23 版开始支持全文索引和全文检索。
删除索引的语法:DROP INDEX index_name ON tableName
三、单列索引和组合索引
为了形象地对比两者,再建一个表:
CREATE TABLE myIndex ( i_testID INT NOT NULL AUTO_INCREMENT, vc_NameVARCHAR(50) NOT NULL, vc_City VARCHAR(50) NOT NULL, i_Age INT NOT NULL,i_SchoolID INT NOT NULL, PRIMARY KEY (i_testID) );
在这 10000条记录里面 7 上 8 下地分布了 5 条 vc_Name="erquan" 的记录,只不过 city,age,school 的组合各不相同。
来看这条 T-SQL:SELECT i_testID FROM myIndex WHEREvc_Name=’erquan’ AND vc_City=’郑州’ AND i_Age=25;
首先考虑建单列索引:
在 vc_Name列上建立了索引。执行 T-SQL 时,MYSQL 很快将目标锁定在了 vc_Name=erquan 的 5 条记录上,取出来放到一中间结果集。在这个结果集里,先排除掉 vc_City 不等于"郑州"的记录,再排除 i_Age 不等于 25 的记录,最后筛选出唯一的符合条件的记录。
虽然在 vc_Name上建立了索引,查询时MYSQL不用扫描整张表,效率有所提高,但离我们的要求还有一定的距离。同样的,在 vc_City 和 i_Age 分别建立的单列索引的效率相似。
为了进一步榨取 MySQL的效率,就要考虑建立组合索引。就是将 vc_Name,vc_City,i_Age 建到一个索引里:
ALTER TABLE myIndex ADD INDEX name_city_age(vc_Name(10),vc_City,i_Age);
建表时,vc_Name长度为 50,这里为什么用 10 呢?因为一般情况下名字的长度不会超过 10,这样会加速索引查询速度,还会减少索引文件的大小,提高 INSERT 的更新速度。
执行 T-SQL时,MySQL 无须扫描任何记录就到找到唯一的记录!!
肯定有人要问了,如果分别在 vc_Name,vc_City,i_Age 上建立单列索引,让该表有 3 个单列索引,查询时和上述的组合索引效率一样吗?大不一样,远远低于我们的组合索引。虽然此时有了三个索引,但 MySQL 只能用到其中的那个它认为似乎是最有效率的单列索引。
建立这样的组合索引,其实是相当于分别建立了
vc_Name,vc_City,i_Age
vc_Name,vc_City
vc_Name
这样的三个组合索引!为什么没有 vc_City,i_Age 等这样的组合索引呢?这是因为 mysql 组合索引“最左前缀”的结果。简单的理解就是只从最左面的开始组合。并不是只要包含这三列的查询都会用到该组合索引,下面的几个 T-SQL 会用到:
SELECT * FROM myIndex WHREE vc_Name="erquan" ANDvc_City="郑州"
SELECT * FROM myIndex WHREEvc_Name="erquan"
而下面几个则不会用到:
SELECT * FROM myIndex WHREE i_Age=20 AND vc_City="郑州"
SELECT * FROM myIndex WHREE vc_City="郑州"
四、使用索引
到此你应该会建立、使用索引了吧?但什么情况下需要建立索引呢?一般来说,在 WHERE和 JOIN 中出现的列需要建立索引,但也不完全如此,因为 MySQL 只对 =,BETWEEN,IN,以及某些时候的LIKE(后面有说明)才会使用索引。
SELECT t.vc_Name FROM testIndex t LEFT JOIN myIndex m ONt.vc_Name=m.vc_Name WHERE m.i_Age=20 AND m.vc_City=’郑州’时,有对 myIndex 表的 vc_City 和 i_Age 建立索引的需要,由于testIndex 表的 vc_Name 开出现在了 JOIN 子句中,也有对它建立索引的必要。
刚才提到了,只有某些时候的 LIKE才需建立索引?是的。因为在以通配符 % 和 _ 开头作查询时,MySQL 不会使用索引,如 SELECT * FROM myIndex WHERE vc_Name like’erquan%’
会使用索引,而 SELECT * FROM myIndex WHEREt vc_Namelike’%erquan’ 就不会使用索引了。
五、索引的不足之处
上面说了那么多索引的好话,它真的有像传说中那么优秀么?当然会有缺点了。
1、虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行 INSERT、UPDATE 和DELETE。因为更新表时,MySQL 不仅要保存数据,还要保存一下索引文件。
2、建立索引会占用磁盘空间的索引文件。一般情况这个问题不太严重,但如果你在一个大表上创建了多种组合索引,索引文件的会膨胀很快。
讲了这么多,无非是想利用索引提高数据库的执行效率。不过索引只是提高效率的一个因素。如果你的MySQL有大数据的表,就需要花时间研究建立最优秀的索引或优化查询语句。
MySQL索引的缺点以及MySQL索引在实际操作中有哪些事项
以下的文章主要介绍的是MySQL索引的缺点以及MySQL索引在实际操作中有哪些事项是值得我们大家注意的,我们大家可能不知道过多的对索引进行使用将会造成滥用,需要的朋友可以了解下
以下的文章主要介绍的是MySQL索引的缺点以及MySQL索引在实际操作中有哪些事项是值得我们大家注意的,我们大家可能不知道过多的对索引进行使用将会造成滥用。因此MySQL索引也会有它的缺点:
虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。
建立索引会占用磁盘空间的索引文件。一般情况这个问题不太严重,但如果你在一个大表上创建了多种组合索引,索引文件的会膨胀很快。
索引只是提高效率的一个因素,如果你的MySQL有大数据量的表,就需要花时间研究建立最优秀的MySQL索引,或优化查询语句。
使用索引的注意事项
使用索引时,有以下一些技巧和注意事项:
1、索引不会包含有NULL值的列
只要列中包含有NULL值都将不会被包含在MySQL索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为NULL。
2、使用短索引
对串列进行索引,如果可能应该指定一个前缀长度。例如,如果有一个CHAR(255)的列,如果在前10个或20个字符内,多数值是惟一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。
3、索引列排序
MySQL查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order
by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序,如果需要最好给这些列创建复合索引。
4、like语句操作
一般情况下不鼓励使用like操作,如果非使用不可,如何使用也是一个问题。like “%aaa%” 不会使用MySQL索引而like “aaa%”可以使用索引。
5、不要在列上进行运算
select * from users where YEAR(adddate)
mysql 主键索引,联合索引,单列索引使用场景
表button
CREATE TABLE `button` (
`id` bigint(20) NOT NULL AUTO_INCREMENT, --主键索引
`button_name` varchar(45) NOT NULL COMMENT ’功能名称’,
`app_id` bigint(20) NOT NULL,
`permission_id` bigint(20) DEFAULT NULL, -- permission_id 和 app_id 联合索引。
`api_id` bigint(20) NOT NULL, --api_id单独索引
PRIMARY KEY (`id`),
KEY `index_app_permission_lianhe` (`permission_id`,`app_id`) USING BTREE,
KEY `index_api_id_dange` (`api_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
主键索引,单独索引,组合索引使用场景及优化
表button 有3个索引,分别是:id主键,联合索引(permission_id,app_id),api_id(单列索引)
button_name 无索引
查询where条件中:
主键索引:
1、主键索引与联合索引同时存在,使用主键索引
2、主键索引与单个索引同时存在,使用主键索引
结论:只要主键索引在,使用主键索引。
联合索引 :
1、联合索引与单列索引列 同时存在,使用单列索引
2、联合索引中列顺序颠倒无影响。
3、联合索引实行最左侧原则,即:单独查询条件中只有permission_id可以使用联合索引,单独查询条件中只有app_id不实用联合索引。
4、如果查询条件中只有app_id,但是select 条件中有 permission_id,则也使用联合索引。
5、select id,app_id from button where app_id=1001; 使用联合索引
6、explain select id,app_id,button_name from button where app_id=1001;不使用联合索引
结论:索引优先级:主键索引,单列索引,组合索引
联合索引中遵从最左侧列原则。
当查询条件和返回结果中仅仅包含联合索引中索引项,也使用联合索引。如第4条。
当查询条件中出现联合索引中非最左侧索引列,返回结果中含义联合索引中的列或者主键则也使用联合索引。
单个索引:
1、查询条件中有单列索引,则使用,无不使用。
事例:
MySQL索引什么情况下创建
索引可以提高数据的检索效率,也可以降低数据库的IO成本,并且索引还可以降低数据库的排序成本。排序分组操作主要消耗的就是CPU资源和内存,所以能够在排序分组操作中好好的利用索引将会极大地降低CPU资源的消耗。
如何判定是否需要创建索引?
1、较频繁地作为查询条件的字段
这个都知道。什么是教频繁呢?分析你执行的所有SQL语句。最好将他们一个个都列出来。然后分析,发现其中有些字段在大部分的SQL语句查询时候都会用到,那么就果断为他建立索引。
2、唯一性太差的字段不适合建立索引
什么是唯一性太差的字段。如状态字段、类型字段。那些只存储固定几个值的字段,例如用户登录状态、消息的status等。这个涉及到了索引扫描的特性。例如:通过索引查找键值为A和B的某些数据,通过A找到某条相符合的数据,这条数据在X页上面,然后继续扫描,又发现符合A的数据出现在了Y页上面,那么存储引擎就会丢弃X页面的数据,然后存储Y页面上的数据,一直到查找完所有对应A的数据,然后查找B字段,发现X页面上面又有对应B字段的数据,那么他就会再次扫描X页面,等于X页面就会被扫描2次甚至多次。以此类推,所以同一个数据页可能会被多次重复的读取,丢弃,在读取,这无疑给存储引擎极大地增加了IO的负担。
3、更新太频繁地字段不适合创建索引
当你为这个字段创建索引时候,当你再次更新这个字段数据时,数据库会自动更新他的索引,所以当这个字段更新太频繁地时候那么就是不断的更新索引,性能的影响可想而知。大概被检索几十次会更新一次的字段才比较符合建立索引的规范。而如果一个字段同一个时间段内被更新多次,那么果断不能为他建立索引。
4、不会出现在where条件中的字段不该建立索引
这个相信大家都知道。
--》
mysql数据库中的索引有那些、有什么用_MySQL
bitsCN.com
mysql数据库中的索引有那些、有什么用
本文主要讲述了如何加速动态网站的MySQL索引分析和优化。
一、什么是索引?
索引用来快速地寻找那些具有特定值的记录,所有MySQL索引都以B-树的形式保存。如果没有索引,执行查询时MySQL必须从第一个记录开始扫描整个表的所有记录,直至找到符合要求的记录。表里面的记录数量越多,这个操作的代价就越高。如果作为搜索条件的列上已经创建了索引,MySQL无需扫描任何记录即可迅速得到目标记录所在的位置。如果表有1000个记录,通过索引查找记录至少要比顺序扫描记录快100倍。
假设我们创建了一个名为people的表:
CREATE TABLE people ( peopleid SMALLINT NOT NULL,
name CHAR(50) NOT NULL );
然后,我们完全随机把1000个不同name值插入到people表。在数据文件中name列没有任何明确的次序。如果我们创建了name列的索引,MySQL将在索引中排序name列,对于索引中的每一项,MySQL在内部为它保存一个数据文件中实际记录所在位置的“指针”。因此,如果我们要查找name等于“Mike”记录的peopleid(SQL命令为“SELECT peopleid FROM people WHERE name=’Mike’;”),MySQL能够在name的索引中查找“Mike”值,然后直接转到数据文件中相应的行,准确地返回该行的peopleid(999)。在这个过程中,MySQL只需处理一个行就可以返回结果。如果没有“name”列的索引,MySQL要扫描数据文件中的所有记录,即1000个记录!显然,需要MySQL处理的记录数量越少,则它完成任务的速度就越快。
二、索引的类型
MySQL提供多种索引类型供选择:
普通索引 :
这是最基本的索引类型,而且它没有唯一性之类的限制。普通索引可以通过以下几种方式创建:
创建索引,例如CREATE INDEXON tablename (列的列表);
修改表,例如ALTER TABLE tablename ADD INDEX (列的列表);
创建表的时候指定索引,例如CREATE TABLE tablename ( (列的列表) );
唯一性索引:
这种索引和前面的“普通索引”基本相同,但有一个区别:索引列的所有值都只能出现一次,即必须唯一。唯一性索引可以用以下几种方式创建:
创建索引,例如CREATE UNIQUE INDEXON tablename (列的列表);
修改表,例如ALTER TABLE tablename ADD UNIQUE (列的列表);
创建表的时候指定索引,例如CREATE TABLE tablename ( (列的列表) );
主键 :
主键是一种唯一性索引,但它必须指定为“PRIMARY KEY”。如果你曾经用过AUTO_INCREMENT类型的列,你可能已经熟悉主键之类的概念了。主键一般在创建表的时候指定,例如“CREATE TABLE tablename ( , PRIMARY KEY (列的列表) ); ”。但是,我们也可以通过修改表的方式加入主键,例如“ALTER TABLE tablename ADD PRIMARY KEY (列的列表); ”。每个表只能有一个主键。
全文索引:
MySQL从3.23.23版开始支持全文索引和全文检索。在MySQL中,全文索引的索引类型为FULLTEXT。全文索引可以在VARCHAR或者TEXT类型的列上创建。它可以通过CREATE TABLE命令创建,也可以通过ALTER TABLE或CREATE INDEX命令创建。对于大规模的数据集,通过ALTER TABLE(或者CREATE INDEX)命令创建全文索引要比把记录插入带有全文索引的空表更快。本文下面的讨论不再涉及全文索引,要了解更多信息,请参见MySQL documentation。
三、单列索引与多列索引
索引可以是单列索引,也可以是多列索引。下面我们通过具体的例子来说明这两种索引的区别。假设有这样一个people表:
CREATE TABLE people ( peopleid
SMALLINT NOT NULL AUTO_INCREMENT,
firstname CHAR(50) NOT NULL, lastname CHAR(50) NOT NULL,
age SMALLINT NOT NULL,
townid SMALLINT NOT NULL, PRIMARY KEY (peopleid) );
下面是我们插入到这个people表的数据:
这个数据片段中有四个名字为“Mikes”的人(其中两个姓Sullivans,两个姓McConnells),有两个年龄为17岁的人,还有一个名字与众不同的Joe Smith。
这个表的主要用途是根据指定的用户姓、名以及年龄返回相应的peopleid。例如,我们可能需要查找姓名为Mike Sullivan、年龄17岁用户的peopleid(SQL命令为SELECT peopleid FROM people WHERE firstname=’Mike’ AND lastname=’Sullivan’ AND age=17;)。由于我们不想让MySQL每次执行查询就去扫描整个表,这里需要考虑运用索引。
首先,我们可以考虑在单个列上创建索引,比如firstname、lastname或者age列。如果我们创建firstname列的索引(ALTER TABLE people ADD INDEX firstname (firstname);),MySQL将通过这个索引迅速把搜索范围限制到那些firstname=’Mike’的记录,然后再在这个“中间结果集”上进行其他条件的搜索:它首先排除那些lastname不等于“Sullivan”的记录,然后排除那些age不等于17的记录。当记录满足所有搜索条件之后,MySQL就返回最终的搜索结果。
由于建立了firstname列的索引,与执行表的完全扫描相比,MySQL的效率提高了很多,但我们要求MySQL扫描的记录数量仍旧远远超过了实际所需要的。虽然我们可以删除firstname列上的索引,再创建lastname或者age列的索引,但总地看来,不论在哪个列上创建索引搜索效率仍旧相似。
为了提高搜索效率,我们需要考虑运用多列索引。如果为firstname、lastname和age这三个列创建一个多列索引,MySQL只需一次检索就能够找出正确的结果!下面是创建这个多列索引的SQL命令:
ALTER TABLE people ADD INDEX fname_lname_age (firstname,lastname,age);
由于索引文件以B-树格式保存,MySQL能够立即转到合适的firstname,然后再转到合适的lastname,最后转到合适的age。在没有扫描数据文件任何一个记录的情况下,MySQL就正确地找出了搜索的目标记录!
那么,如果在firstname、lastname、age这三个列上分别创建单列索引,效果是否和创建一个firstname、lastname、age的多列索引一样呢?答案是否定的,两者完全不同。当我们执行查询的时候,MySQL只能使用一个索引。如果你有三个单列的索引,MySQL会试图选择一个限制最严格的索引。但是,即使是限制最严格的单列索引,它的限制能力也肯定远远低于firstname、lastname、age这三个列上的多列索引。
四、最左前缀
多列索引还有另外一个优点,它通过称为最左前缀(Leftmost Prefixing)的概念体现出来。继续考虑前面的例子,现在我们有一个firstname、lastname、age列上的多列索引,我们称这个索引为fname_lname_age。当搜索条件是以下各种列的组合时,MySQL将使用fname_lname_age索引:
firstname,lastname,age
firstname,lastname
firstname
从另一方面理解,它相当于我们创建了(firstname,lastname,age)、(firstname,lastname)以及(firstname)这些列组合上的索引。下面这些查询都能够使用这个fname_lname_age索引:
SELECT peopleid FROM people
WHERE firstname=’Mike’ AND lastname=’Sullivan’ AND age=’17’;
SELECT peopleid FROM people WHERE firstname=’Mike’ AND lastname=’Sullivan’;
SELECT peopleid FROM people WHERE firstname=’Mike’;
The following queries cannot use the index at all:
SELECT peopleid FROM people WHERE lastname=’Sullivan’;
SELECT peopleid FROM people WHERE age=’17’;
SELECT peopleid FROM people WHERE lastname=’Sullivan’ AND age=’17’;
五、选择索引列
在性能优化过程中,选择在哪些列上创建索引是最重要的步骤之一。可以考虑使用索引的主要有两种类型的列:在WHERE子句中出现的列,在join子句中出现的列。请看下面这个查询:
SELECT age ## 不使用索引
FROM people WHERE firstname=’Mike’ ## 考虑使用索引
AND lastname=’Sullivan’ ## 考虑使用索引
这个查询与前面的查询略有不同,但仍属于简单查询。由于age是在SELECT部分被引用,MySQL不会用它来限制列选择操作。因此,对于这个查询来说,创建age列的索引没有什么必要。下面是一个更复杂的例子:
SELECT people.age, ##不使用索引
town.name ##不使用索引
FROM people LEFT JOIN town ON
people.townid=town.townid ##考虑使用索引
WHERE firstname=’Mike’ ##考虑使用索引
AND lastname=’Sullivan’ ##考虑使用索引
与前面的例子一样,由于firstname和lastname出现在WHERE子句中,因此这两个列仍旧有创建索引的必要。除此之外,由于town表的townid列出现在join子句中,因此我们需要考虑创建该列的索引。那么,我们是否可以简单地认为应该索引WHERE子句和join子句中出现的每一个列呢?差不多如此,但并不完全。我们还必须考虑到对列进行比较的操作符类型。MySQL只有对以下操作符才使用索引:=,BETWEEN,IN,以及某些时候的LIKE。可以在LIKE操作中使用索引的情形是指另一个操作数不是以通配符(%或者_)开头的情形。例如,“SELECT peopleid FROM people WHERE firstname LIKE ’Mich%’;”这个查询将使用索引,但“SELECT peopleid FROM people WHERE firstname LIKE ’%ike’;”这个查询不会使用索引
bitsCN.com
Mysql几种索引类型的区别及适用情况
如大家所知道的,Mysql目前主要有以下几种索引类型:FULLTEXT,HASH,BTREE,RTREE。
那么,这几种索引有什么功能和性能上的不同呢?
FULLTEXT
即为全文索引,目前只有MyISAM引擎支持。其可以在CREATE TABLE ,ALTER TABLE ,CREATE INDEX 使用,不过目前只有 CHAR、VARCHAR ,TEXT 列上可以创建全文索引。值得一提的是,在数据量较大时候,现将数据放入一个没有全局索引的表中,然后再用CREATE INDEX创建FULLTEXT索引,要比先为一张表建立FULLTEXT然后再将数据写入的速度快很多。
全文索引并不是和MyISAM一起诞生的,它的出现是为了解决WHERE name LIKE “%word%"这类针对文本的模糊查询效率较低的问题。在没有全文索引之前,这样一个查询语句是要进行遍历数据表操作的,可见,在数据量较大时是极其的耗时的,如果没有异步IO处理,进程将被挟持,很浪费时间,当然这里不对异步IO作进一步讲解,想了解的童鞋,自行谷哥。
全文索引的使用方法并不复杂:
创建ALTER TABLE table ADD INDEX `FULLINDEX` USING FULLTEXT(`cname1`);
使用SELECT * FROM table WHERE MATCH(cname1) AGAINST (‘word‘ MODE );
其中, MODE为搜寻方式(IN BOOLEAN MODE ,IN NATURAL LANGUAGE MODE ,IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION / WITH QUERY EXPANSION)。
关于这三种搜寻方式,愚安在这里也不多做交代,简单地说,就是,布尔模式,允许word里含一些特殊字符用于标记一些具体的要求,如+表示一定要有,-表示一定没有,*表示通用匹配符,是不是想起了正则,类似吧;自然语言模式,就是简单的单词匹配;含表达式的自然语言模式,就是先用自然语言模式处理,对返回的结果,再进行表达式匹配。
对搜索引擎稍微有点了解的同学,肯定知道分词这个概念,FULLTEXT索引也是按照分词原理建立索引的。西文中,大部分为字母文字,分词可以很方便的按照空格进行分割。但很明显,中文不能按照这种方式进行分词。那又怎么办呢?这个向大家介绍一个Mysql的中文分词插件Mysqlcft,有了它,就可以对中文进行分词,想了解的同学请移步Mysqlcft,当然还有其他的分词插件可以使用。
HASH
Hash这个词,可以说,自打我们开始码的那一天起,就开始不停地见到和使用到了。其实,hash就是一种(key=》value)形式的键值对,如数学中的函数映射,允许多个key对应相同的value,但不允许一个key对应多个value。正是由于这个特性,hash很适合做索引,为某一列或几列建立hash索引,就会利用这一列或几列的值通过一定的算法计算出一个hash值,对应一行或几行数据(这里在概念上和函数映射有区别,不要混淆)。在java语言中,每个类都有自己的hashcode()方法,没有显示定义的都继承自object类,该方法使得每一个对象都是唯一的,在进行对象间equal比较,和序列化传输中起到了很重要的作用。hash的生成方法有很多种,足可以保证hash码的唯一性,例如在MongoDB中,每一个document都有系统为其生成的唯一的objectID(包含时间戳,主机散列值,进程PID,和自增ID)也是一种hash的表现。额,我好像扯远了-_-!
由于hash索引可以一次定位,不需要像树形索引那样逐层查找,因此具有极高的效率。那为什么还需要其他的树形索引呢?
在这里愚安就不自己总结了。引用下园子里其他大神的文章:来自 14的路 的MySQL的btree索引和hash索引的区别
(1)Hash 索引仅仅能满足"=","IN"和"《=》"查询,不能使用范围查询。由于 Hash 索引比较的是进行 Hash 运算之后的 Hash 值,所以它只能用于等值的过滤,不能用于基于范围的过滤,因为经过相应的 Hash 算法处理之后的 Hash 值的大小关系,并不能保证和Hash运算前完全一样。(2)Hash 索引无法被用来避免数据的排序操作。由于 Hash 索引中存放的是经过 Hash 计算之后的 Hash 值,而且Hash值的大小关系并不一定和 Hash 运算前的键值完全一样,所以数据库无法利用索引的数据来避免任何排序运算;(3)Hash 索引不能利用部分索引键查询。对于组合索引,Hash 索引在计算 Hash 值的时候是组合索引键合并后再一起计算 Hash 值,而不是单独计算 Hash 值,所以通过组合索引的前面一个或几个索引键进行查询的时候,Hash 索引也无法被利用。(4)Hash 索引在任何时候都不能避免表扫描。前面已经知道,Hash 索引是将索引键通过 Hash 运算之后,将 Hash运算结果的 Hash 值和所对应的行指针信息存放于一个 Hash 表中,由于不同索引键存在相同 Hash 值,所以即使取满足某个 Hash 键值的数据的记录条数,也无法从 Hash 索引中直接完成查询,还是要通过访问表中的实际数据进行相应的比较,并得到相应的结果。(5)Hash 索引遇到大量Hash值相等的情况后性能并不一定就会比B-Tree索引高。对于选择性比较低的索引键,如果创建 Hash 索引,那么将会存在大量记录指针信息存于同一个 Hash 值相关联。这样要定位某一条记录时就会非常麻烦,会浪费多次表数据的访问,而造成整体性能低下。
愚安我稍作补充,讲一下HASH索引的过程,顺便解释下上面的第4,5条:
当我们为某一列或某几列建立hash索引时(目前就只有MEMORY引擎显式地支持这种索引),会在硬盘上生成类似如下的文件:
hash值
存储地址
1db54bc745a1
77#45b5
4bca452157d4
76#4556,77#45cc…
…
hash值即为通过特定算法由指定列数据计算出来,磁盘地址即为所在数据行存储在硬盘上的地址(也有可能是其他存储地址,其实MEMORY会将hash表导入内存)。
这样,当我们进行WHERE age = 18 时,会将18通过相同的算法计算出一个hash值==》在hash表中找到对应的储存地址==》根据存储地址取得数据。
所以,每次查询时都要遍历hash表,直到找到对应的hash值,如(4),数据量大了之后,hash表也会变得庞大起来,性能下降,遍历耗时增加,如(5)。
BTREE
BTREE索引就是一种将索引值按一定的算法,存入一个树形的数据结构中,相信学过数据结构的童鞋都对当初学习二叉树这种数据结构的经历记忆犹新,反正愚安我当时为了软考可是被这玩意儿好好地折腾了一番,不过那次考试好像没怎么考这个。如二叉树一样,每次查询都是从树的入口root开始,依次遍历node,获取leaf。
BTREE在MyISAM里的形式和Innodb稍有不同
在 Innodb里,有两种形态:一是primary key形态,其leaf node里存放的是数据,而且不仅存放了索引键的数据,还存放了其他字段的数据。二是secondary index,其leaf node和普通的BTREE差不多,只是还存放了指向主键的信息.
而在MyISAM里,主键和其他的并没有太大区别。不过和Innodb不太一样的地方是在MyISAM里,leaf node里存放的不是主键的信息,而是指向数据文件里的对应数据行的信息.
RTREE
RTREE在mysql很少使用,仅支持geometry数据类型,支持该类型的存储引擎只有MyISAM、BDb、InnoDb、NDb、Archive几种。
相对于BTREE,RTREE的优势在于范围查找.
各种索引的使用情况
(1)对于BTREE这种Mysql默认的索引类型,具有普遍的适用性
(2)由于FULLTEXT对中文支持不是很好,在没有插件的情况下,最好不要使用。其实,一些小的博客应用,只需要在数据采集时,为其建立关键字列表,通过关键字索引,也是一个不错的方法,至少愚安我是经常这么做的。
(3)对于一些搜索引擎级别的应用来说,FULLTEXT同样不是一个好的处理方法,Mysql的全文索引建立的文件还是比较大的,而且效率不是很高,即便是使用了中文分词插件,对中文分词支持也只是一般。真要碰到这种问题,Apache的Lucene或许是你的选择。
(4)正是因为hash表在处理较小数据量时具有无可比拟的素的优势,所以hash索引很适合做缓存(内存数据库)。如mysql数据库的内存版本Memsql,使用量很广泛的缓存工具Mencached,NoSql数据库redis等,都使用了hash索引这种形式。当然,不想学习这些东西的话Mysql的MEMORY引擎也是可以满足这种需求的。
(5)至于RTREE,愚安我至今还没有使用过,它具体怎么样,我就不知道了。有RTREE使用经历的同学,到时可以交流下!
Mysql几种索引类型的区别及适用情况
标签:
mysql索引的应用场景以及如何使用
唯一的是什么?
1.索引列(字段)的所有值都只能出现一次,即必须唯一
--------------------------------------------------------------------------------
主键索引与唯一索引的区别
1.主键是一种约束,唯一索引是一种索引,两者在本质上是不同的。
2.主键创建后一定包含一个唯一性索引,唯一性索引并不一定就是主键。
3.唯一性索引列允许空值,而主键列不允许为空值。
4.主键列在创建时,已经默认为空值++ 唯一索引了。
5.一个表最多只能创建一个主键,但可以创建多个唯一索引。
6.主键更适合那些不容易更改的唯一标识,如自动递增列、身份证号等。
7.主键可以被其他表引用为外键,而唯一索引不能。 ?
--------------------------------------------------------------------------------
复合索引
1.用户可以在多个列上建立索引,这种索引叫做复合索引(组合索引)。
2.就是几个字段联合在一起组成一个索引.复合索引的创建方法与创建单一索引的方法完全一样。
3.但复合索引在数据库操作期间所需的开销更小,可以代替多个单一索引。
4.当表的行数远远大于索引键的数目时,使用这种方式可以明显加快表的查询速度。
--------------------------------------------------------------------------------
(abc) (ab) (ac)(bc)(a) (b) (c)
1.复合索引又叫联合索引。
2. abc ab a ac 可以
3.对于复合索引:Mysql从左到右的使用索引中的字段,一个查询可以只使用索引中的一部份,但只能是最左侧部分。
4.例如索引是key index (a,b,c).可以支持a | a,b| a,b,c 3种组合进行查找,但不支持b,c进行查找,当最左侧字段是常量引用时,索引就十分有效。
--------------------------------------------------------------------------------
除复合索引外,什么情况下索引被使用,什么情况下不会被使用
1.建立索引的目的就是帮助查询,如果查寻用不到则索引就没有必要建立。
2.如果表是经常需要更新的也不适合做索引 。频繁更新会导致索引也会频繁更新,降低写的效率。
3.唯一性差的字段不适合创建索引。
4.当给一个字段创建了索引的话,而这个字段要进行like模糊查询的话,那么这个值左边不可以有%,因为索引查询是要从左到右的,你如果给它加上%后,左边的值不是确定的话,它会找不到这个索引。所以在使用like模糊查询的时候,值得左边不可以有%。
5. order by 不会使用索引
6. or当前后2个字段都有索引时才可以索引出来 否则不可以。
7.如果数据表过大(5w以上)则有些字段(字符型长度超过(40))不适合作为索引。查询大量数据时,索引有效,但是慢
8.不使用索引的原因:因为索引时会先过一遍索引在过一遍数据
--------------------------------------------------------------------------------
全文检索:
1.全文检索就是FULLTEXT,用于MyISAM表,在列类型为CHAR、VARCHAR或TEXT列上创建。
2.将数据装载到一个没有FULLTEXT索引的表中,然后再使用ALTER TABLE (或CREATE INDEX)创建索引,这将是非常快的。
3.将数据装载到一个已经有FULLTEXT索引的表中,将是非常慢的。
4. MySQL自带的全文索引只能对英文进行全文检索。要检索中文用sphinx。
5.创建全文检索:alter table表名add fulltext index索引名(列名,..(可以有多个,可以有一个)
6.在创建表的时候建全文检索:CREATE TABLE article (
7.id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
8.FULLTEXT (title, content) --在title和content列上创建全文索引
);
--------------------------------------------------------------------------------
场景
1.当数据多且字段值有相同的值得时候用普通索引。
2.当字段多且字段值没有重复的时候用唯一索引。
3.当有多个字段名都经常被查询的话用复合索引。
4.普通索引不支持空值,唯一索引支持空值。
5.但是,若是这张表增删改多而查询较少的话,就不要创建索引了,因为如果你给一列创建了索引,那么对该列进行增删改的时候,都会先访问这一列的索引,
6.若是增,则在这一列的索引内以新填入的这个字段名的值为名创建索引的子集,
7.若是改,则会把原来的删掉,再添入一个以这个字段名的新值为名创建索引的子集,
8.若是删,则会把索引中以这个字段为名的索引的子集删掉。
9.所以,会对增删改的执行减缓速度,
10.所以,若是这张表增删改多而查询较少的话,就不要创建索引了。
11.更新太频繁地字段不适合创建索引。
12.不会出现在where条件中的字段不该建立索引。
--------------------------------------------------------------------------------
索引创建
CREATE INDEX INDEX_NAME ON TABLE_NAME(PROPERTY_NAME);
其中UNIQUE和CLUSTERED为可选项,分别是建立唯一索引和聚簇索引,具体解释为:
UNIQUE:表示此索引的每一个索引值只对应唯一的数据。
CLUSTERED:表示要建立的索引时聚簇索引,即索引项的顺序与表中记录的物理顺序一致的索引组织
ALTER TABLE table_name ADD INDEX index_name (column_list)
mysql索引的应用场景以及如何使用
标签:col如何alt也会自动物理bodynot选项
数据库基础:讲解MySQL索引的概念及数据库索引的应用[2]
五 索引分类
直接创建索引和间接创建索引
直接创建索引 CREATE INDEX mycolumn_index ON mytable (myclumn)
间接创建索引 定义主键约束或者唯一性键约束 可以间接创建索引
普通索引和唯一性索引
普通索引 CREATE INDEX mycolumn_index ON mytable (myclumn)
唯一性索引 保证在索引列中的全部数据是唯一的 对聚簇索引和非聚簇索引都可以使用
CREATE UNIQUE COUSTERED INDEX myclumn_cindex ON mytable(mycolumn)
单个索引和复合索引
单个索引 即非复合索引
复合索引 又叫组合索引 在索引建立语句中同时包含多个字段名 最多 个字段
CREATE INDEX name_index ON username(firstname lastname)
聚簇索引和非聚簇索引(聚集索引 群集索引)
聚簇索引 物理索引 与基表的物理顺序相同 数据值的顺序总是按照顺序排列
CREATE CLUSTERED INDEX mycolumn_cindex ON mytable(mycolumn) WITH
ALLOW_DUP_ROW(允许有重复记录的聚簇索引)
非聚簇索引 CREATE UNCLUSTERED INDEX mycolumn_cindex ON mytable(mycolumn)
六 索引的使用
当字段数据更新频率较低 查询使用频率较高并且存在大量重复值是建议使用聚簇索引
经常同时存取多列 且每列都含有重复值可考虑建立组合索引
复合索引的前导列一定好控制好 否则无法起到索引的效果 如果查询时前导列不在查询条件中则该复合索引不会被使用 前导列一定是使用最频繁的列
多表操作在被实际执行前 查询优化器会根据连接条件 列出几组可能的连接方案并从中找出系统开销最小的最佳方案 连接条件要充份考虑带有索引的表 行数多的表;内外表的选择可由公式 外层表中的匹配行数*内层表中每一次查找的次数确定 乘积最小为最佳方案
where子句中对列的任何操作结果都是在sql运行时逐列计算得到的 因此它不得不进行表搜索 而没有使用该列上面的索引;如果这些结果在查询编译时就能得到 那么就可以被sql优化器优化 使用索引 避免表搜索(例 select * from record where substring(card_no )=
&& select * from record where card_no like % )任何对列的操作都将导致表扫描 它包括数据库函数 计算表达式等等 查询时要尽可能将操作移至等号右边
where条件中的 in 在逻辑上相当于 or 所以语法分析器会将in ( ′ ′)转化为column= ′ or column= ′来执行 我们期望它会根据每个or子句分别查找 再将结果相加 这样可以利用column上的索引;但实际上它却采用了 or策略 即先取出满足每个or子句的行 存入临时数据库的工作表中 再建立唯一索引以去掉重复行 最后从这个临时表中计算结果 因此 实际过程没有利用column上索引 并且完成时间还要受tempdb数据库性能的影响 in or子句常会使用工作表 使索引失效;如果不产生大量重复值 可以考虑把子句拆开;拆开的子句中应该包含索引
要善于使用存储过程 它使sql变得更加灵活和高效
lishixinzhi/Article/program/MySQL/201311/29603MySQL怎么使用索引
MySQL如何使用索引 ? ? ?给定特定的列的值查找满足条件的行,索引的使用能够加快查找的速度。如果没有索引,MySQL将从第一行记录开始,穿越整个表找到相应的记录,表越大,相应的查询的代价也就越大。如果针对查询中的列有索引,MySQL就能在数据文件中快速确
MySQL如何使用索引
? ? ?给定特定的列的值查找满足条件的行,索引的使用能够加快查找的速度。如果没有索引,MySQL将从第一行记录开始,穿越整个表找到相应的记录,表越大,相应的查询的代价也就越大。如果针对查询中的列有索引,MySQL就能在数据文件中快速确定需要查找的位置,再也不用穿越整个表来捞数据了。如果一个表有1000条数据,这样至少能比整表顺序读取捞数据快100倍。如果你的查询结果包含了整表的大部分记录,它也比没有索引整表捞数据要快,至少减少了磁盘的寻址时间。
?
? ? 大部分的MySQL索引(PRIMARY KEY, UNIQUE, INDEX, FULLTEXT)都是以B-Tree结构来存储,而空间数据索引则使用R-Tree结构来存储,内存表则使用哈希索引。
?
? ? 字符串在创建索引时会自动去除首尾的空白。
?
? ? MySQL会在以下操作时使用索引:
快速查找匹配where语句的行记录时。
预计能够缩小结果的范围时。如果查询能够匹配多个索引,MySQL一般会使用能够过滤出结果最少的索引。
join操作时从其他表捞数据。在join时,如果声明关联的列类型和大小相同,MySQL在使用索引时能够更加高效。在这里,如果VARCHAR 和CHAR的大小相同,他们在类型上会被认为是相同的。例如VARCHAR(10)和CHAR(10)是大小相同的,但是VARCHAR(10)和CHAR(15)的大小是不同的。
? ? ? ?在两个不同的列之间进行比较,例如string和temporal,或者numeric,不能方便直接进行比较,将妨碍 ?
? ? ? ?索引的使用。假设一个numeric列和一个string列进行比较,对于numeric列中给定的一个值,比如1,它可能会和
? ? ? ? ?string中的很多值相同,例如:’1’, ’ 1’, ’00001’, 或者 ’01.e1’。string列上的任何索引对这种查询没有任何意义和帮助。
获取已有索引列的MIN()、MAX()值。在执行这两个聚合函数的时候,预处理过程会在使用该列的索引之前会首先检查where语句中是否包含有其他索引列的等于限定条件,并从该索引中分别查询一次MIN和MAX,并将获取到的常量值返回,整个查询将一次返回,而不用做原始列的全索引扫描。例如:在已有索引的列column1上获取其MIN、MAX值,如果在where中包含有”column2=常量“,而column2、column1构建有复合索引,这种情况下,MySQL将不会查找column1的索引,而是在column2、column1的复合索引中进行查找,并能一次获取到结果,不用穿越整个索引。
如果在一个已经排序并分组的最左前缀索引上执行sort或者group,例如:ORDER BY key_part1, key_part2,key_part1, key_part2是复合索引的列,如果所有的key都是DESC的,key将会反序读取。
在某些情况下,一个查询通过优化,可以不用通过获取行数据而得到结果。如果一个查询只使用了numeric列,并且这些列参与构建了最左前缀索引,那么MySQL可以直接从索引中获取到需要的结果,而不用访问具体的数据。这也就是所谓的”覆盖索引“,例如:
SELECT key_part3 FROM tbl_name
WHERE key_part1=1
?key_part1、key_part3属于一个最左前缀索引。假设执行以下的SQL语句:
SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;
?如果在col1、col2上有一个复合索引,对应的查询结果就能直接获取到。如果在col1、col2只有分别的单列索引,优化器就会尝试使用索引合并进行优化,或者看哪个索引返回的结果集更好,然后根据该结果集去表中读取数据。
? ? ? ? ?如果该表有一个多列索引,该索引的任意最左前缀都能被优化器使用。例如,如果在(col1, col2, col3)上有一个三列索引,则基于(col1)、(col1,col2)、(col1,col2,col3)的查询都会使用到该索引。
? ? ? ? 如果使用的列不能构成一个最左前缀,MySQL就无法使用索引了,假设有如下的SQL查询:
SELECT * FROM tbl_name WHERE col1=val1;
SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;
SELECT * FROM tbl_name WHERE col2=val2;
SELECT * FROM tbl_name WHERE col2=val2 AND col3=val3;
? ? ? ?如果在(col1, col2, col3)构建索引,那么就只有头两个SQL查询能够使用索引。第三个、第四个查询虽然也使用到了被索引的列,但是(col2) 和(col2, col3)不是(col1, col2, col3)的最左前缀。
?
?
B-Tree索引的特性
? ? ? ? B-Tree索引在进行=, 》, 》=,
SELECT * FROM tbl_name WHERE key_col LIKE ’Patrick%’;
SELECT * FROM tbl_name WHERE key_col LIKE ’Pat%_ck%’;
? ? ? ? 而下面的语句将不会使用索引:
SELECT * FROM tbl_name WHERE key_col LIKE ’%Patrick%’;
SELECT * FROM tbl_name WHERE key_col LIKE other_col;
? ? ? ? 在第一句中,LIKE操作的字符串以通配符开头,而第二句中,LIKE操作的不是一个常量字符串。
? ? ? ? 如果使用... LIKE ’%string%’, 并且string不超过三个字符,MySQL将使用Turbo Boyer-Moore算法来初始化这个字符串模式,然后使用这个模式进行快速查找。
?
? ? ? ? 对于创建了索引的列col_name,如果在where中包含有col_name is NULL,在操作时,MySQL也将使用索引。
?
? ? ? ? 在一个AND组中,必须包含有索引前缀,才能在执行过程中使用索引,下面的WHERE语句将使用索引:
... WHERE index_part1=1 AND index_part2=2 AND other_column=3
/* index = 1 OR index = 2 */
... WHERE index=1 OR A=10 AND index=2
/* optimized like "index_part1=’hello’" */
... WHERE index_part1=’hello’ AND index_part3=5
/* 能在index1上使用索引,不能再index2或者index3上使用索引 */
... WHERE index1=1 AND index2=2 OR index1=3 AND index3=3;
? ? ? ? ?下面的WHERE语句无法使用索引:
/* index_part1索引没有被使用 */
... WHERE index_part2=1 AND index_part3=2
/* 两部分的索引都没有使用 */
... WHERE index=1 OR A=10
/* 没有索引跨越所有行 */
... WHERE index_part1=1 OR index_part2=10
? ? ? ? ?
?
? ? ? ?有时候,及时有索引满足条件,MySQL也不会使用它,会发生这种状况的一种情形是MySQL优化器认为使用索引会导致对整表很大一部分数据的访问,在这种情况下,直接的全表扫描可能更快,它花费的寻址时间更少。不过,如果这种查询使用limit限定只返回结果中的部分行,MySQL就会使用索引,这种只返回少量行的操作,通过索引会更快。
?

更多文章:
16进制转10进制 python(有符号十六进制转换为十进制 怎么转换啊)
2025年9月13日 11:00
广数980手机编程软件(哪里能找到广数980TD系统程序传输软件(非串口))
2025年7月27日 21:15
学会js和mysql能做什么(学完mysql之后做个什么项目好呢)
2026年7月23日 00:30
web服务器配置个人总结(Windows 的Web服务器配置方法介绍)
2025年6月13日 11:15
back down(back off与back up 与back down的区别)
2026年3月1日 01:30
powerful binoculars(英语作文《journey to the sea》)
2026年1月22日 14:00
template意思(template <class T>到底是什么意思啊求解.)
2026年3月16日 18:45
prompt action(i appreciate your prompt action中文什么意思)
2025年7月22日 19:30
indexof功能怎么用(vb要实现indexof 功能该怎么做)
2025年11月14日 16:30
refresh英文翻译(refresh和refurbish的区别是什么)
2025年12月3日 14:00
conventional的名词形式(“烟花爆竹”英语怎么说)
2026年4月6日 13:00
phpcmsx源码(在phpcms做的网站中,直接修改源代码,不在后台进行,过段时间,代码为什么会被自动改回来)
2025年10月7日 04:15








