搜索
首页数据库mysql教程高性能MySql进化论(七):正确的使用索引
高性能MySql进化论(七):正确的使用索引Jun 07, 2016 pm 03:01 PM
mysql使用引擎数据库正确索引高性能

数据库引擎利用索引提高查询效率,同时也针对索引增加了很多的优化策略,但是在使用索引的过程中也有很多的细节问题需要注意,如果忽略了这些问题,辛辛苦苦建立的索引可能得不到很好的应用,而且有可能还会对性能有一定的影响,下面列出了在使用索引的过程

数据库引擎利用索引提高查询效率,同时也针对索引增加了很多的优化策略,但是在使用索引的过程中也有很多的细节问题需要注意,如果忽略了这些问题,辛辛苦苦建立的索引可能得不到很好的应用,而且有可能还会对性能有一定的影响,下面列出了在使用索引的过程中需要遵守的原则

1        保持单纯的列

所谓的“单纯的列”指的就是在作为查询条件时,不要使用运算符,函数对字段进行处理,否则相关的索引将不能使用

下面列出两种最常见的错误情况
(1) select wordfrom dictionary where id+1=999;

      不应该使用id+1的方式

(2) selectword from dictionary where to_days(CURRENT_DATE)-to_days(id)

      不应该使用TO_DAYS(id)的方式

 

2        正确的采用“前缀索引”的前缀长度

在有些时候,需要使用长字符串作为索引,这样的索引由于占用的空间比较大,以及排序的时候值之间的比较会花费很多的时间,效率会比较低。对于这种情况可以只使用这个字段的前N个字符作为索引的值,这种策略就叫做”前缀索引”。比如,在MYSQL中如果需要使用BLOB/TEXT类型的字段作为索引的话,那么必须使用前缀索引,因为这几种类型不允许作为索引。

 

使用“前缀索引”会带来选择性的问题,比如某张表的长字段索引记录如下,如果采用整个字段的值作为索引的值的话虽然效率很低,但是匹配到最后应该只有一条记录与之相符,这种情况下选择性为1,是最高的。如果采用4个字符作为前缀,那么其实这个索引也就失去了价值,因为它的数量和表记录的数量是相等的,不管怎么优化,做的也都是全表扫描。所以前缀长度的选择非常的重要

ABCDEFGHIJKDDD8

ABCDEFFSKDJKJKD7

ABCDKJH65654654K

ABCDEFGHIJKKJKJG

ABCDEFGHIJKFFFFEJ

可以采取以下方式确定前缀长度,应用别的书籍上的例子,这个例子中city是索引字段

         2.1 首先确定整个表索引值的选择率:

 select count(distinct city)/ count(*) from City_Demo;             

              假设执行的结果是0.0312

         2.2 算出几个候选长度的选择率

 

SELECT COUNT(DISTINCTLEFT(city, 3))/COUNT(*) AS sel3,

COUNT(DISTINCT LEFT(city,4))/COUNT(*) AS sel4,

COUNT(DISTINCT LEFT(city,5))/COUNT(*) AS sel5,

COUNT(DISTINCT LEFT(city,6))/COUNT(*) AS sel6,

COUNT(DISTINCT LEFT(city,7))/COUNT(*) AS sel7

FROM city_demo;

+--------+--------+--------+--------+--------+

| sel3 |       sel4 |       sel5 |  sel6|         sel7 |

+--------+--------+--------+--------+--------+

| 0.0239 | 0.0293 | 0.0305 | 0.0309 | 0.0310 |

       2.3   选一个最靠近的值,从比较的结果看,应该选7作为前缀的长度

       2.4  接下来创建这个前缀索引

               ALTER TABLE sakila.city_demo ADD KEY (city(7));

              最后要指出的是“前缀索引”的缺点:MYSQL无法使用前缀索引做orderby,group by, 以及覆盖索引(后面会提到)

 

3        组合索引中字段的顺序问题

在创建B-Tree的组合索引时,由于B-Tree的匹配顺序是按照存储的顺序来比较的,所以说如果前面的字段可以过滤掉更多的记录的话,后面的条件就会比较更少的记录,当然效率也就更高,用下面的组合索引做个简单的解释

NAME

AREA

 

如果把NAME放在第一个位置,那么在用AREA进行比较时,可能只用10条记录需要比较,如果把AREA放在第一个位置,那么在用NAME进行比较是,可能会有1000条记录需要比较,可以简单的推断出需要把NAME放在索引的第一列,这个原理决定了Hash索引是不适用该规则的。

 

上面的小例子,可以通过字段的选择率来确定索引的字段顺序,转换成SQL的表示方式如下,

 

SELECT COUNT(DISTINCT NAME)/COUNT(*) AS name_selectivity,

COUNT(DISTINCT AREA)/COUNT(*) AS area_selectivity,

COUNT(*)

 FROM student\G

*************************** 1. row***************************

area_selectivity: 0.0001

name_selectivity: 0.0373

COUNT(*): 16049

 

结论:把结果中选择率高的字段放在组合的前面

 

4        聚合索引(Cluster Indexes)

首先要说明的是“聚合索引”并不是指某种具体的索引类型,而是指索引数据的存储方式。其具体的实现细节和数据库引擎实现紧密相关,基本的思想是”将索引和数据行保存在一个数据结构中,且数据行和相邻的键值存储在一起”。如果查询的结果都可以被索引覆盖的话,就不需要再回数据库中进行数据的检索。

 

在Oracle中,可以显示的指定哪些索引为聚合索引。在目前版本的MySQL中,各个存储引擎还不能通过“任意指定”的方式来设置聚合索引。在InnoDB中默认的情况会使用主键作为聚合索引,如果没有建立主键,会选择一个“非空且唯一”的索引来代替,如果 “非空且唯一”的索引也不存在,它会自定义一个主键作为聚合索引。

 

最后需要指出的是,因为这种存储方式中,相邻键值的数据行是存储在一起的,所以应该尽量采用键值递增的插入方式。

如果是使用UUID这种随机的主键,会导致大量的随机IO访问,插入效率会很低

 

 

5        覆盖索引(Converting Indexes)

覆盖索引是指:索引的字段包含了所有要查询的字段,就成为覆盖索引。

例如Student表中在(Name,Area)上建立了索引:

select name,area from student wherename=’Eric’ 这样的查询就成为是被索引覆盖的,从执行计划上看,如果EXPLAIN一条查询的Extra列包含“Using Index”就说明这条查询被索引覆盖了。

 

通常情况下利用索引查询到记录的时候,首先会查询到索引的Node,然后根据索引Node中存储的记录指针再到数据库的中查找记录,这种方式也就相当于进行了两次查询,而且数据库记录查询的效率往往会比较低。覆盖索引由于它本身就包含了要查询的字段值,也就避免了对数据库记录的访问,从而极大的提高了查询的效率。

 

有一点需要注意,因为覆盖索引用到的是索引字段的值,而“Hash/空间/全文” 索引中并没有存储索引字段的实际值,所以他们是不支持覆盖索引的。


关于覆盖索引,除了上面提出的问题外,还需要注意MYSQL的版本问题。MYSQL5.5以后的版本对该特性提供了更好的支持,所以尽可能还是使用最新的版本。

 

6        索引顺序扫描排序

MYSQL 可以按照索引顺序扫描(Explain 中的type为index)以及排序操作来实现排序功能。

 

如果使用了索引顺序扫描以及覆盖索引可以使排序的速度大大的提高,如果索引不能包含所有要查询的列,则在取每条记录值的时候都需要根据记录指针去查找对应的记录,这有可能会带来大量的随机I/O的产生,从而使查询效率下降。所以在设计索引的时候,既要考虑到查询条件,也要考虑到排序操作

 

为了使索引更好的服务于排序动作,在拼写SQL的过程中有以下几个问题需要注意

(1)    使用“覆盖索引”

(2)    索引的顺序和order by的顺序一致,且所有列的排序方向一致

(3)    多表关联排序时,order by的条件字段全部都是第一个表的

(4)    Order by 和where一样,也要遵守“最左原则“

(5)    如果where或者join中指定了某个列为常量,则可以弥补规则(4),

例如  INDEX(Name,Age,ID) 则 ….where name=”Eric” order by age, id 也可以使用索引顺序扫描排序

7        轻便的索引

MYSQL允许在相同的Column上创建多个索引,MYSQL需要单独维护每个重复的索引,而且查询优化器也会在这些重复的索引上花时间,从而可能导致整体性能的下降。

所以应该尽量保持索引的"轻便"

 

·             重复的索引

定义:在相同的列上,按照相同的顺序,创建相同类型的索引。

例如 下面的语句将在ID上创建三个索引,对于Primary KEY而言,UNIQUE以及INDEX都是重复的

Create table test(

 ID int not null PRIMARY KEY,

 UNIQUE(ID),

 INDEX(ID),

)


·             冗余的索引

这里的“冗余“指的是多个索引有着相同的类型,且功能重复。

例如对于B-Tree索引而言,如果创建了索引(A,B),再创建索引(A),则(A)就被认为是重复的,但是如果创建了(B)则不被认为是冗余的。

 

冗余的索引一般是发生在扩展的索引的时候,例如已经存在了一个索引(A),有人为了满足新的查询需求,创建了一个新的索引(A,B),这个时候(A)就成了冗余的索引,应该进行删除,或者是用(A)来扩展成(A,B)

 

有时候冗余的索引也能带来查询性能上的提升,例如当需要向索引中添加了一个超长的字符串字段,因为这个字段会导致索引存储空间的变大,导致了查询效率的降低,所以适当的使用冗余索引对性能会有帮助。

 

可以通过对INFORMATION_SCHEMA中的数据来判断索引是否是重复/冗余,也可以通过专门的工具例如Percona-Toolkit的pt-duplicate-key-checker 来检测(http://www.percona.com/doc/percona-toolkit/2.1/pt-duplicate-key-checker.html)

·             未使用的索引

 

和前面两种情况类似,当系统中存在大量未使用的索引时,同样对查询的效率会有影响,可以通过以下两种方式来判断那些索引时未使用的

 

(1)     在Percona或者是MariaDB中,通过打开userstates服务器变量,然后正常运行一段时间,最后通过INFORMATION_SCHEMA.INDEX_STATISTICS变量来判断

(2)     通过专门的工具,例如Percona-Toolkit的pt-index-usage来判断,该工具不仅可以查出那些索引是没有被使用的,还可以了解查询的执行计划(http://www.percona.com/doc/percona-toolkit/2.1/pt-index-usage.html)

 

需要注意的是,并不是未使用的索引就是没有用的索引,例如有些索引的功能是唯一性约束,虽然该索引一直没有被使用,但是却可以避免产生重复的数据,这种类型的索引在处理的时候需要小心

 

 

 

 

 

 

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
如何使用Go语言创建高性能的MySQL更新操作如何使用Go语言创建高性能的MySQL更新操作Jun 17, 2023 pm 01:28 PM

在现代的Web应用程序中,数据库是不可避免的一部分。MySQL是一种常用的关系型数据库管理系统,与许多编程语言兼容。Go语言是一种自带并发性能且易于编写的编程语言。在本文中,我们将介绍如何结合Go语言和MySQL创建高性能的数据库更新操作。连接MySQL数据库在开始之前,您需要确保已经安装并配置了MySQL数据库。我们使用Go语言内置的MySQL驱动程序来连

使用Go语言编写高性能的全文检索引擎使用Go语言编写高性能的全文检索引擎Jun 15, 2023 pm 11:51 PM

随着互联网时代的到来,全文检索引擎越来越受到人们的重视。在无数的网页、文档和数据中,我们需要快速地找到所需的内容,这就需要使用高效的全文检索引擎。Go语言是一种以效率而闻名的编程语言,它的设计目标是提高代码的执行效率和性能。因此,使用Go语言编写全文检索引擎可以大大提高其运行效率和性能。本文将介绍如何使用Go语言编写高性能的全文检索引擎。一、理解全文检索引擎

使用Go语言编写高性能的正则表达式匹配使用Go语言编写高性能的正则表达式匹配Jun 15, 2023 pm 10:56 PM

随着数据量的不断增大,正则表达式匹配成为了程序中常用的操作之一。而在Go语言中,由于其天然的并行ism,以及与底层系统的交互性和高效性,使得Go语言的正则表达式匹配极具优势。那么如何使用Go语言编写高性能的正则表达式匹配呢?一、了解正则表达式在使用正则表达式前,我们首先需要了解正则表达式,了解其基本语法规则以及常用的匹配字符,使我们能够在编写正则表达式时更加

如何使用Go语言创建高性能的MySQL删除操作如何使用Go语言创建高性能的MySQL删除操作Jun 17, 2023 am 11:04 AM

随着数据量的增加,数据库中的删除操作往往会成为程序的瓶颈。为了提高删除操作的性能,可以考虑使用Go语言。Go语言是一种高效的编程语言,能够很好地支持并发和网络编程,同时也有很强的类型检查功能,可靠性和安全性都很高。下面,我们将介绍如何使用Go语言创建高性能的MySQL删除操作。使用Go的并发机制首先,可以使用Go语言的goroutine并发机制来加速删除操作

Swoole与MongoDB的整合:构建高性能的文档数据库系统Swoole与MongoDB的整合:构建高性能的文档数据库系统Jun 14, 2023 am 11:51 AM

在现代企业应用程序开发中,需要处理海量数据和高并发的访问请求。为了满足这些需求,开发人员需要使用高性能的数据库系统,以确保系统的稳定性和可扩展性。本文将介绍如何使用Swoole和MongoDB构建高性能的文档数据库系统。Swoole是一个基于PHP语言开发的异步网络通信框架,它能够大大提高PHP应用程序的性能和并发能力。MongoDB是一种流行的文档数据库,

高性能PHP爬虫的实现方法高性能PHP爬虫的实现方法Jun 13, 2023 pm 03:22 PM

随着互联网的发展,网页中的信息量越来越大,越来越深入,很多人需要从海量的数据中快速地提取出自己需要的信息。此时,爬虫就成了重要的工具之一。本文将介绍如何使用PHP编写高性能的爬虫,以便快速准确地从网络中获取所需的信息。一、了解爬虫基本原理爬虫的基本功能就是模拟浏览器去访问网页,并获取其中的特定信息。它可以模拟用户在网页浏览器中的一系列操作,比如向服务器发送请

使用fiber框架构建高性能的Web应用使用fiber框架构建高性能的Web应用Jun 03, 2023 pm 09:10 PM

随着互联网的快速发展,越来越多的企业和个人开始涉足Web应用的开发领域,而如何构建高性能的Web应用已经成为人们关注的焦点之一。对于Web应用的性能来说,最主要的就是服务器端的处理能力和响应时间。近年来,随着技术的发展,有许多新的框架被提了出来,其中Fiber框架因其高性能和易用性备受青睐。Fiber是一个轻量级的Go语言Web框架,它的主要特点就是高性能和

Swoole实现高性能的社交功能Swoole实现高性能的社交功能Jun 13, 2023 pm 04:04 PM

随着社交媒体的飞速发展,越来越多的企业和个人需要在网站或应用中实现社交功能,以便更好地与用户互动和沟通。而为了实现高并发、低延迟的社交功能,开发者们需要选择一些高性能的工具和框架。其中,Swoole就是一个很不错的选择。Swoole是一款基于PHP的异步、高性能网络通信框架,它旨在提高Web应用程序的性能,特别是在处理高并发请求时。Swoole可以与PHP的

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前By尊渡假赌尊渡假赌尊渡假赌
仓库:如何复兴队友
4 周前By尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒险:如何获得巨型种子
4 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

SecLists

SecLists

SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

Atom编辑器mac版下载

Atom编辑器mac版下载

最流行的的开源编辑器

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

功能强大的PHP集成开发环境