十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
首先来看看表是否有索引的命令
创新互联公司自2013年起,是专业互联网技术服务公司,拥有项目成都网站设计、做网站网站策划,项目实施与项目整合能力。我们以让每一个梦想脱颖而出为使命,1280元方城做网站,已为上家服务,为方城各地企业和个人服务,联系电话:18980820575
show index from 表名;
看到主键索引,索引类型是BTREE(二叉树)
正是因为这个二叉树算法,让查询速度快很多,二叉树的原理,就是取最中间的一个数,然后把大于这个数的往右边排,小于这个数的就向左排,每次减半,然后依次类推,每次减半,形成一个树状结构图
例如上面的例子,我们不使用索引的话,需要查询11次才把编号为4的数据取出,如果加上索引,我们只需要4次就可以取出。
如大家所知道的,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`[,cname2…]);
使用SELECT * FROM table WHERE MATCH(cname1[,cname2…]) 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引擎也是可以满足这种需求的。
因为索引多。同一条个数据,NOSQL占用空间是一般SQL数据库的3-5倍。
你可以理解成NOSQL默认开启全字段索引和全文索引什么的。
其实在十万级以下的数据,只要SQL建好索引的情况并不比NOSQL慢。NOSQL主要是用于千万上亿级的时候。
你有没有想过如何使用搜索功能在所有整站中实现!互联网博客和网站,大多数都采用MySQL数据库。MySQL提供了一个美妙的方式实施一个小的搜索引擎,在您的网站(全文检索)。所有您需要做的是拥有的MySQL 4.x及以上。MySQL提供全文检索功能,我们可以用它来 ??实现搜索功能。
首先,让我们为我们的例子中设置一个示例表。我们将创建一个名为第一个表。
CREATE TABLE articles (
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(200),
body TEXT,
FULLTEXT (title,body)
);
在此表中还可以添加一些示例数据。执行后,插入查询。
INSERT INTO articles (title,body) VALUES
('MySQL Tutorial','DBMS stands for DataBase ...'),
('How To Use MySQL Well','After you went through a ...'),
('Optimizing MySQL','In this tutorial we will show ...'),
('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
('MySQL vs. YourSQL','In the following database comparison ...'),
('MySQL Security','When configured properly, MySQL ...');
一旦样本数据是准备好,我们可以开始我们的全文检索功能。
自然语言全文搜索
尝试我们的示例表上执行下面的SELECT查询。
SELECT * FROM articles
WHERE MATCH (title,body) AGAINST ('database');
你就能看到结果如下:
在下面的数据库比较5 MySQL与YourSQL的...
MySQL教程DBMS 1代表数据库...
我们在上面的SQL查询(标题,正文)反对(“数据库”)的比赛,选择所有的记录,列标题和正文进行全文搜索。
您可以修改该查询,并创建您自己的版本,以自己的数据库中执行全文搜索。
布尔全文搜索
它可能发生,你要指定某些关键字在您的搜索条件。此外,您可能要忽略某些关键字。布尔全文搜索可以用来执行这些要求的全文检索。
检查下面的SELECT查询。
SELECT * FROM articles WHERE MATCH (title,body)
AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE);
如果您发现上述选择查询,我们增加了布尔MODE反对()。这个查询将获取MySQL的关键字,但不YourSQL关键字的所有记录。请注意+和-我们以前指定的关键字!
在执行此功能,MySQL使用什么有时也被称为布尔逻辑作为暗示,其中:+代表与-代表不是[无操作员]暗示或
以下是几个例子布尔搜索条件。
“苹果香蕉
查找行至少包含两个词之一。
“+苹果+果汁”
寻找包含两个单词的行。
“+苹果Macintosh
查找行包含“苹果”,但排名的行,如果它们也包含“麦金塔”。
“+苹果Macintosh的”
查找行包含“苹果”这个词,而不是“麦金塔”。
'+苹果Macintosh的“
查找包含单词“苹果”的行,但如果该行也包含单词“麦金塔”,速度比如果行不低。这是“软”比“+苹果Macintosh电脑”,为“麦金塔”的存在,导致该行不能在所有返回的搜索。
'+苹果+(营业额馅饼)“
行包含“苹果”和“营业额”,或“苹果”和“馅饼”(任何顺序)的话,但排名“苹果的营业额”比“苹果馅饼“。
限制
支持全文检索的MyISAM表只。MySQL 4.1中,使用多个字符设置一个单一的表内的支持。然而,在一个FULLTEXT索引的所有列,必须使用相同的字符集和校对规则。MATCH()列列表必须匹配完全在一些列清单表的FULLTEXT索引定义,除非这场比赛()是在布尔模式。布尔模式搜索,可以做非索引列,虽然他们很可能是缓慢的。
使用索引是数据库性能优化的必备技能之一。在MySQL数据库中,有四种索引:聚集索引(主键索引)、普通索引、唯一索引以及我们这里将要介绍的全文索引(FULLTEXT INDEX)。
全文索引(也称全文检索)是目前搜索引擎使用的一种关键技术。它能够利用「分词技术「等多种算法智能分析出文本文字中关键字词的频率及重要性,然后按照一定的算法规则智能地筛选出我们想要的搜索结果。在这里,我们就不追根究底其底层实现原理了,现在我们来看看在MySQL中如何创建并使用全文索引。
在MySQL中,创建全文索引相对比较简单。例如,我们有一个文章表(article),其中有主键ID(id)、文章标题(title)、文章内容(content)三个字段。现在我们希望能够在title和content两个列上创建全文索引,article表及全文索引的创建SQL语句如下:
--创建article表
CREATE TABLE article (
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(200),
content TEXT,
FULLTEXT (title, content) --在title和content列上创建全文索引
);
上面就是在创建表的同时建立全文索引的SQL示例。此外,如果我们想要给已经存在的表的指定字段创建全文索引,同样以article表为例,我们可以使用如下SQL语句进行创建:
--给现有的article表的title和content字段创建全文索引
--索引名称为fulltext_article
ALTER TABLE article
ADD FULLTEXT INDEX fulltext_article (title, content)
在MySQL中创建全文索引之后,现在就该了解如何使用了。众所周知,在数据库中进行模糊查询是使用LIKE关键字进行查询,例如:
SELECT * FROM article WHERE content LIKE '%查询字符串%'
那么,我们使用全文索引也是这样用的吗?当然不是,我们必须使用特有的语法才能使用全文索引进行查询。例如,我们想要在article表的title和content列中全文检索指定的查询字符串,可以如下编写SQL语句:
SELECT * FROM article WHERE MATCH(title, content) AGAINST('查询字符串')
强烈注意:MySQL自带的全文索引只能用于数据库引擎为MyISAM的数据表,如果是其他数据引擎,则全文索引不会生效。此外,MySQL自带的全文索引只能对英文进行全文检索,目前无法对中文进行全文检索。如果需要对包含中文在内的文本数据进行全文检索,我们需要采用Sphinx(斯芬克斯)/Coreseek技术来处理中文。本站将会在后续文章中对Sphinx以及Coreseek进行介绍。
备注1:目前,使用MySQL自带的全文索引时,如果查询字符串的长度过短将无法得到期望的搜索结果。MySQL全文索引所能找到的词的默认最小长度为4个字符。另外,如果查询的字符串包含停止词,那么该停止词将会被忽略。
备注2:如果可能,请尽量先创建表并插入所有数据后再创建全文索引,而不要在创建表时就直接创建全文索引,因为前者比后者的全文索引效率要高。