扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
InnoDB的全文索引使用反向索引的设计。反向索引存储了一个单词(word)列表,对于每个单词,都有一个文档的列表,来标识这个单词出现的地方。为了支持临近搜索(proximity search),每个单词的位置信息也以字节偏移的方式存储。
我们提供的服务有:成都网站制作、成都做网站、外贸营销网站建设、微信公众号开发、网站优化、网站认证、解放ssl等。为1000+企事业单位解决了网站和推广的问题。提供周到的售前咨询和贴心的售后服务,是有科学管理、有技术的解放网站制作公司
当创建了InnoDB全文索引,一系列的索引表会一同被创建,见下面的例子:
最前面的六个表包含了反向索引,它们被称作附属索引表(auxiliary index table)。当输入的表被索引(tokenized)后,每个独立的单词(亦称作“tokens”)会被携带其DOC_ID和位置信息插入到索引表中。根据单词第一个字符的字符集排序权重,在六个索引表中对单词进行完全排序和分区。
反向索引分区到六个附属索引表以支持并行的索引创建。默认有2个线程复制索引(Tokenize)、排序、插入单词和关联数据到索引表中。工作的线程的数量由 innodb_ft_sort_pll_degree 配置项控制的。对于大表的全文索引,可以考虑增加线程数量。
如果主表创建在 xx表空间,索引表存储在它们自己的表空间中。反之,索引表存储于其索引的表空间中。
前面例子展示的另外一种索引表被称作通用索引表,它们被用于全文索引的“删除处理(deletion handing)”和存储内部状态。不同于为每个全文索引都各自创建的反向索引表,这组表对特定表的所有全文索引都是共用的。
即使全文索引删掉了,通用索引(Common Index)也会被保留,当全文索引删除后,为这个索引而创建的FTS_DOC_ID列依然保留,因为移除FTS_DOC_ID列会导致重构之前被索引的表。管理FTS_DOC_ID列需要用到通用索引表。
为了防止大量并发读写附属表,InnoDB使用全文索引缓存去临时缓存最近的插入行。在存满并刷入磁盘之前,缓存的内容一直存储在内存之中,可以通过查询 INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE 表去查看最近缓存的插入行。
缓存和批处理刷新行为避免了对辅助索引表的频繁更新,频繁更新可能会在繁忙的插入和更新期间导致并发访问问题。批处理还避免了对同一个word的多次插入,最大化的减少了重复的条目。相同的word会先merge再刷入到磁盘中,而不是为每个word单独插入,这样提高了插入效率并且使得索引附属表尽可能的小。
全文索引缓存只缓存最近插入的行,查询时,已经刷入磁盘(附属索引表)的数据不会再回到索引缓存中。附属索引表中的内容是直接查询的,最终返回的结果返回前需要将附属索引表的结果和索引缓存中的结果合并。
InnoDB使用被称作DOC_ID的唯一文件描述符,将全文索引中的单词与该单词在文档中的记录映射起来。映射关系需要索引表中的 FTS_DOC_ID 列。在创建全文索引时,如果没有定义 FTS_DOC_ID 列,InnoDB会自动的加入一个隐藏的 FTS_DOC_ID 列。下面是一个例子,
CREATE FULLTEXT INDEX ft_index ON xxxxxxxx(CONTEXT)
[2021-11-12 18:14:04] [HY000][124] InnoDB rebuilding table to add column FTS_DOC_ID
重点看一下这一行: [HY000][124] InnoDB rebuilding table to add column FTS_DOC_ID ,InnoDB重新构建了这个表,并且添加了一个列 FTS_DOC_ID 。
在CREATE TABLE的过程中添加 FTS_DOC_ID 的时间成本要低于在已经有数据的表上建立全文索引。如果在表加载数据之前定义 FTS_DOC_ID 列,这个表和它的索引都不需要为了新增列而重新构建。如果你不需要考虑 CREATE FULLTEXT INDEX 的性能,可以让InnoDB为你创建 FTS_DOC_ID 列。InnoDB会新增一个隐藏的 FTS_DOC_ID 列,并且在 FTS_DOC_ID 上建立唯一索引(FTS_DOC_ID_INDEX)。如果你想自行创建 FTS_DOC_ID 列,这个列必须定义为 BIGINT UNSIGNED NOT NULL 且命名为FTS_DOC_ID(全大写),如下例子:
如果你自行定义 FTS_DOC_ID 列的话,你需要负责管理这个列,避免空值(empty)或者重复值。 FTS_DOC_ID 的值是不能被重复利用的,所以也就是说 FTS_DOC_ID 的值是需要一直增加的。
或者,你可以在 FTS_DOC_ID 列上创建所必须的唯一索引FTS_DOC_ID_INDEX(全大写)。
mysql CREATE UNIQUE INDEX FTS_DOC_ID_INDEX on opening_lines(FTS_DOC_ID);
如果你没有创建FTS_DOC_ID_INDEX,InnoDB会自动创建。
在MySQL 5.7.13前,允许最大FTS_DOC_ID与最新的FTS_DOC_ID之间的间隔为10000,在MySQL 5.7.13及之后的版本中,这个允许的间隔为65535。
为了避免重新构建表,FTS_DOC_ID列在删除了全文索引之后依然被保留。
删除被索引文件的一个记录,可能会在附属索引表中产生非常多的小的删除项,在并发访问时,会产生热点问题。为了避免这个问题,每当被索引表中的记录被删除时,会将被删文档的DOC_ID记录在一个特别的 FTS_*_DELETED 表中,同时全文索引中已经索引了的记录依然被保存。在返回查询结果前,使用 FTS_*_DELETED 中的信息去过滤掉已经删除掉了的DOC_ID。这种设计的优势在于删除速度快且消耗低。不好的地方在于索引的大小不能随着记录的删除而立即减少。为了删除已删除记录在全文索引中的项,需要对被索引的表执行OPTIMIZE TABLE,配合[ innodb_optimize_fulltext_only=ON ],去重构全文索引。
细节略,有例子:
全文搜索只能看到已经提交了的数据。
你可以通过查询下面的INFORMATION_SCHEMA表,来监控或测试InnoDB的一些特殊文本处理。
默认的分词器不支持中文,不能检索到中文中的英文单词。
InnoDB默认的Stopwords:
select * from information_schema.INNODB_FT_DEFAULT_STOPWORD;
SQL中的关键词(保留关键字):
Shell中的关键词:for,while,echo
其他:###, ***, --,
被索引表数据量、索引表数据量
模糊匹配与严格匹配的性能差距
需要将 innodb_optimize_fulltext_only 配置为ON,这里是否需要DBA在MySQL镜像中修改?
innodb_optimize_fulltext_only 设置为ON后,对系统有何影响需要评估。
innodb_optimize_fulltext_only
执行的时间、频率。
MySQL内建的全文检索解析器使用单词之间的空白作为分隔符以标识单词的头尾,但是这里有个限制,对于表意文字,它是没有单词分隔符的。为了解决这个限制,MySQL提供了支持中文、日语、韩语的 ngram 解析器。ngram解析器支持InnoDB和MyISAM。
Ngram是内建在服务中的插件,像其他自建在服务中的插件一样,服务启动时会自动加载它。全文检索的语法参考上面( Section 12.10, “Full-Text Search Functions” ),这里只讨论一些不同的地方。除了单词的最小、最大长度配置项([ innodb_ft_min_token_size ]innodb_ft_max_token_size,ft_min_word_len,ft_max_word_len,全文检索依赖一些配置项都是可以使用的。
Ngram默认索引的单词(token)的大小为2( 2bigram )。例如,索引的大小为2,Ngram解析器解析字符串“abc def”为四个单词元素(tokens):“ab”, “bc”, “de” and “ef”。
ngram token size is configurable using the ngram_token_size configuration option, which has a minimum value of 1 and maximum value of 10.
作为只读变量, ngram_token_size 只能在启动配置或者配置文件中指定
与默认的解析器相差不大,多了一句: xxx WITH PARSER ngram
Ngram在解析时去除空格,如
MySQL内建的默认全文检索解析器将单词与Stopword列表中的做对比,如果单词与Stopword列表中的元素相同的话,这个单词则不会被索引。对于Ngram解析器,Stopword的处理方式不同。Ngram解析器不排除与stopword列表中的条目相等的token,而是排除包含stopwords的token。例如,假设 ngram_token_size=2 ,包含“a,b”的文档将被解析为 “a,” h和“,b”。如果将逗号(“,”)定义为停止字,则 “a,”和“,b”都将不会加入索引中,因为它们包含逗号。
例子:
默认Ngram解析器使用默认的Stopword列表,这里面含有英文的Stopword。如果需要中文的Stopword,需要你自己创建。
Stopword的长度超过 ngram_token_size则会被忽略。
有两个文档,一个包含“ab”,另一个包含“abc”。对于搜索文本“abc”将转换成“ab”,“bc”。
略。
For example, The search phrase “abc” is converted to “ab bc”, which returns documents containing “abc” and “ab bc”.
The search phrase “abc def” is converted to “ab bc de ef”, which returns documents containing “abc def” and “ab bc de ef”. A document that contains “abcdef” is not returned.
使用Ngram解析器好处是支持了中文的检索
MySQL支持全文索引和搜索功能。在MySQL中可以在CHAR、VARCHAR或TEXT列使用FULLTETXT来创建全文索引。
FULLTEXT索引主要用MATCH()...AGAINST语法来实现搜索:
MySQL的全文搜索存在以下局限:
通常来说MySQL自带的全文搜索使用起来局限性比较大,性能和功能都不太成熟,主要适用于小项目,大项目还是建议使用elasticsearch来做全文搜索。
ElasticSearch是一个分布式的开源搜索和分析引擎,适用于所有类型的数据,包括文本、数字、地理空间、结构化和非结构化数据,以下简称ES。
Elasticsearch 在 Apache Lucene 的基础上开发而成,Elasticsearch 以其简单的 REST 风格 API、分布式特性、速度和可扩展性而闻名,是 Elastic Stack 的核心组件。Elastic Stack 是适用于数据采集、充实、存储、分析和可视化的一组开源工具。
Elasticsearch 的实现原理主要分为以下几个步骤,首先用户将数据提交到Elasticsearch 数据中心,再通过分词控制器去将对应的数据分词,将其权重和分词结果一并存入数据,当用户搜索数据时候,再根据权重将结果排名,打分,再将返回结果呈现给用户。
由于ES是基于RESTfull Web接口的,因此我们直接按照惯例传递JSON参数调用接口即可实现增删改查,并且不需要我们做额外的管理操作就可以直接索引文档,ES已经内置了所有的缺省操作,可以自动帮我们定义类型。
再次执行PUT,会对库中已有的id为1的数据进行覆盖,每修改一次_version字段的版本号就会加1。
默认搜索会返回前10个结果:
返回的几个关键词:
查询字符串搜索,可以像传递URL参数一样传递查询语句。
精确查询:
全文搜索:
以上两种方法都需要考虑数据更改后如何与ES进行同步。
你有没有想过如何使用搜索功能在所有整站中实现!互联网博客和网站,大多数都采用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:如果可能,请尽量先创建表并插入所有数据后再创建全文索引,而不要在创建表时就直接创建全文索引,因为前者比后者的全文索引效率要高。
索引是一种特殊的文件(InnoDB 数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针。索引不是万能的,索引可以加快数据检索操作,但会使数据修改操作变慢。每修改数据记录,索引就必须刷新一次。为了在某种程度上弥补这一缺陷,许多 SQL 命令都有一个 DELAY_KEY_WRITE 项。这个选项的作用是暂时制止 MySQL 在该命令每插入一条新记录和每修改一条现有之后立刻对索引进行刷新,对索引的刷新将等到全部记录插入/修改完毕之后再进行。在需要把许多新记录插入某个数据表的场合,DELAY_KEY_WRITE 选项的作用将非常明显。另外,索引还会在硬盘上占用相当大的空间。因此应该只为最经常查询和最经常排序的数据列建立索引。注意,如果某个数据列包含许多重复的内容,为它建立索引就没有太大的实际效果。
从理论上讲,完全可以为数据表里的每个字段分别建一个索引,但 MySQL 把同一个数据表里的索引总数限制为16个。
1.InnoDB 数据表的索引
与 InnoDB数据表相比,在 InnoDB 数据表上,索引对 InnoDB 数据表的重要性要大得多。在 InnoDB 数据表上,索引不仅会在搜索数据记录时发挥作用,还是数据行级锁定机制的苊、基础。“数据行级锁定”的意思是指在事务操作的执行过程中锁定正在被处理的个别记录,不让其他用户进行访问。这种锁定将影响到(但不限于)SELECT、LOCKINSHAREMODE、SELECT、FORUPDATE 命令以及 INSERT、UPDATE 和 DELETE 命令。出于效率方面的考虑,InnoDB 数据表的数据行级锁定实际发生在它们的索引上,而不是数据表自身上。显然,数据行级锁定机制只有在有关的数据表有一个合适的索引可供锁定的时候才能发挥效力。
2.限制
如果 WHERE 子句的查询条件里有不等号(WHERE coloum !=),MySQL 将无法使用索引。类似地,如果 WHERE 子句的查询条件里使用了函数(WHERE DAY(column)=),MySQL 也将无法使用索引。在 JOIN 操作中(需要从多个数据表提取数据时),MySQL 只有在主键和外键的数据类型相同时才能使用索引。
如果 WHERE 子句的查询条件里使用比较操作符 LIKE 和 REGEXP,MySQL 只有在搜索模板的第一个字符不是通配符的情况下才能使用索引。比如说,如果查询条件是 LIKE 'abc%‘,MySQL 将使用索引;如果查询条件是 LIKE '%abc’,MySQL 将不使用索引。
在 ORDER BY 操作中,MySQL 只有在排序条件不是一个查询条件表达式的情况下才使用索引。(虽然如此,在涉及多个数据表查询里,即使有索引可用,那些索引在加快 ORDER BY 方面也没什么作用)。如果某个数据列里包含许多重复的值,就算为它建立了索引也不会有很好的效果。比如说,如果某个数据列里包含的净是些诸如 “0/1” 或 “Y/N” 等值,就没有必要为它创建一个索引。 1.普通索引
普通索引(由关键字 KEY 或 INDEX 定义的索引)的唯一任务是加快对数据的访问速度。因此,应该只为那些最经常出现在查询条件(WHERE column =)或排序条件(ORDER BY column)中的数据列创建索引。只要有可能,就应该选择一个数据最整齐、最紧凑的数据列(如一个整数类型的数据列)来创建索引。
2.唯一索引
普通索引允许被索引的数据列包含重复的值。比如说,因为人有可能同名,所以同一个姓名在同一个“员工个人资料”数据表里可能出现两次或更多次。
如果能确定某个数据列将只包含彼此各不相同的值,在为这个数据列创建索引的时候就应该用关键字UNIQUE 把它定义为一个唯一索引。这么做的好处:一是简化了 MySQL 对这个索引的管理工作,这个索引也因此而变得更有效率;二是 MySQL 会在有新记录插入数据表时,自动检查新记录的这个字段的值是否已经在某个记录的这个字段里出现过了;如果是,MySQL 将拒绝插入那条新记录。也就是说,唯一索引可以保证数据记录的唯一性。事实上,在许多场合,人们创建唯一索引的目的往往不是为了提高访问速度,而只是为了避免数据出现重复。
3.主索引
在前面已经反复多次强调过:必须为主键字段创建一个索引,这个索引就是所谓的“主索引”。主索引与唯一索引的唯一区别是:前者在定义时使用的关键字是 PRIMARY 而不是 UNIQUE。
4.外键索引
如果为某个外键字段定义了一个外键约束条件,MySQL 就会定义一个内部索引来帮助自己以最有效率的方式去管理和使用外键约束条件。
5.复合索引
索引可以覆盖多个数据列,如像 INDEX (columnA, columnB) 索引。这种索引的特点是 MySQL 可以有选择地使用一个这样的索引。如果查询操作只需要用到 columnA 数据列上的一个索引,就可以使用复合索引 INDEX(columnA, columnB)。不过,这种用法仅适用于在复合索引中排列在前的数据列组合。比如说,INDEX (A,B,C) 可以当做 A 或 (A,B) 的索引来使用,但不能当做 B、C 或 (B,C) 的索引来使用。 在为 CHAR 和 VARCHAR 类型的数据列定义索引时,可以把索引的长度限制为一个给定的字符个数(这个数字必须小于这个字段所允许的最大字符个数)。这么做的好处是可以生成一个尺寸比较小、检索速度却比较快的索引文件。在绝大多数应用里,数据库中的字符串数据大都以各种各样的名字为主,把索引的长度设置为10~15 个字符已经足以把搜索范围缩小到很少的几条数据记录了。在为 BLOB 和 TEXT 类型的数据列创建索引时,必须对索引的长度做出限制;MySQL 所允许的最大索引全文索引文本字段上的普通索引只能加快对出现在字段内容最前面的字符串(也就是字段内容开头的字符)进行检索操作。如果字段里存放的是由几个、甚至是多个单词构成的较大段文字,普通索引就没什么作用了。这种检索往往以的形式出现,这对 MySQL 来说很复杂,如果需要处理的数据量很大,响应时间就会很长。
这类场合正是全文索引(full-textindex)可以大显身手的地方。在生成这种类型的索引时,MySQL 将把在文本中出现的所有单词创建为一份清单,查询操作将根据这份清单去检索有关的数据记录。全文索引即可以随数据表一同创建,也可以等日后有必要时再使用下面这条命令添加:
ALTER TABLE tablename ADD FULLTEXT(column1,column2)有了全文索引,就可以用 SELECT 查询命令去检索那些包含着一个或多个给定单词的数据记录了。下面是这类查询命令的基本语法:
SELECT * FROM tablename
WHERE MATCH (column1,column2) AGAINST('word1','word2','word3')
上面这条命令将把 column1 和 column2 字段里有 word1、word2 和 word3 的数据记录全部查询出来。
注解:InnoDB 数据表不支持全文索引。 只有当数据库里已经有了足够多的测试数据时,它的性能测试结果才有实际参考价值。如果在测试数据库里只有几百条数据记录,它们往往在执行完第一条查询命令之后就被全部加载到内存里,这将使后续的查询命令都执行得非常快--不管有没有使用索引。只有当数据库里的记录超过了 1000 条、数据总量也超过了 MySQL 服务器上的内存总量时,数据库的性能测试结果才有意义。
在不确定应该在哪些数据列上创建索引的时候,人们从 EXPLAIN SELECT 命令那里往往可以获得一些帮助。这其实只是简单地给一条普通的 SELECT 命令加一个 EXPLAIN 关键字作为前缀而已。有了这个关键字,MySQL 将不是去执行那条 SELECT 命令,而是去对它进行分析。MySQL 将以表格的形式把查询的执行过程和用到的索引等信息列出来。
在 EXPLAIN 命令的输出结果里,第1列是从数据库读取的数据表的名字,它们按被读取的先后顺序排列。type列指定了本数据表与其它数据表之间的关联关系(JOIN)。在各种类型的关联关系当中,效率最高的是 system,然后依次是 const、eq_ref、ref、range、index 和 All(All 的意思是:对应于上一级数据表里的每一条记录,这个数据表里的所有记录都必须被读取一遍——这种情况往往可以用一索引来避免)。
possible_keys 数据列给出了 MySQL 在搜索数据记录时可选用的各个索引。key 数据列是 MySQL 实际选用的索引,这个索引按字节计算的长度在 key_len 数据列里给出。比如说,对于一个 INTEGER 数据列的索引,这个字节长度将是4。如果用到了复合索引,在 key_len 数据列里还可以看到 MySQL 具体使用了它的哪些部分。作为一般规律,key_len 数据列里的值越小越好。
ref 数据列给出了关联关系中另一个数据表里的数据列的名字。row 数据列是 MySQL 在执行这个查询时预计会从这个数据表里读出的数据行的个数。row 数据列里的所有数字的乘积可以大致了解这个查询需要处理多少组合。
最后,extra 数据列提供了与 JOIN 操作有关的更多信息,比如说,如果 MySQL 在执行这个查询时必须创建一个临时数据表,就会在 extra 列看到 usingtemporary 字样。
1.添加PRIMARY KEY(主键索引)
mysqlALTER TABLE `table_name` ADD PRIMARY KEY ( `column` )
2.添加UNIQUE(唯一索引)
mysqlALTER TABLE `table_name` ADD UNIQUE (
`column`
)
3.添加INDEX(普通索引)
mysqlALTER TABLE `table_name` ADD INDEX index_name ( `column` )
4.添加FULLTEXT(全文索引)
mysqlALTER TABLE `table_name` ADD FULLTEXT ( `column`)
5.添加多列索引
mysqlALTER TABLE `table_name` ADD INDEX index_name ( `column1`, `column2`, `column3` )
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流