搜索
首页数据库mysql教程Mysql索引相关知识分享(公司内部)_MySQL

3.关于索引:

     3.1索引可以改善查询,但会减慢更新,索引不是越多越好,最好不超过字段数的20%(在数据增、删、改比较频繁的表中,索引数量不应超过5个。

     3.2离散程度越小,不适合加索引,例如:不要给性别建索引

        test.status取值范围:0-9,在status列建索引

        mysql> select sql_no_cache * from test where status = 3 order by id limit 80000, 2;

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

        | id     | time1          | time2               | time3      | status |

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

        | 795783 | 20110825150959 | 2011-08-25 15:09:00 | 1314256140 |      3 |

        | 795789 | 20120829052359 | 2012-08-29 05:23:00 | 1346188980 |      3 |

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

        2 rows in set (1.26 sec)

       删除status索引后

        mysql> select sql_no_cache * from test where status = 3 order by id limit 80000, 2;

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

        | id     | time1          | time2               | time3      | status |

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

        | 795783 | 20110825150959 | 2011-08-25 15:09:00 | 1314256140 |      3 |

        | 795789 | 20120829052359 | 2012-08-29 05:23:00 | 1346188980 |      3 |

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

        2 rows in set (0.37 sec)

     3.3.避免在空值(Null)很多的字段上建立索引,大量空值会降低索引效率

     3.4.避免在数据值分布不均的字段上建立索引,个别数据值占总数据量的百分率明显比其它数据值占总数据量的百分率高,表明该字段数据值分布不均,容易引起数据库选择错误索引,生成错误的查询执行计划。

     3.5.在数据量较少且访问频率不高的情况下,如只有一百行记录以下的表不需要建立索引。因为在数据量少的情况下,使用全表扫描效果比走索引更好。

     3.6.字符字段必须建前缀索引

        单字母区分度:26

         4个字母区分度:26*26*26*26=456976

         6个字母区分度:26*26*26*26*26*26=308915776

         CREATE TABLE `test1` (

           `id` int(11) NOT NULL AUTO_INCREMENT,

           `a` char(20) NOT NULL DEFAULT '',

           `b` varchar(14) NOT NULL DEFAULT '00000000000000',

           `c` varchar(14) DEFAULT '00000000000000',

           PRIMARY KEY (`id`),

           KEY `a` (`a`(6))

         ) ENGINE=MyISAM AUTO_INCREMENT=12534199 DEFAULT CHARSET=gbk;

         mysql> select sql_no_cache count(*) from test1;

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

         | count(*) |

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

         | 12534198 |

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

         1 row in set (0.00 sec)

         mysql> select sql_no_cache count(*) from test1 where a = 'tR6cDjx0frXx45yURG1m';

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

         | count(*) |

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

         |        1 |

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

         1 row in set (0.00 sec)

     3.7.不在索引列做运算,尽量不用外键(InnoDB)

     3.8.唯一索引:在建立索引的字段所有数值都具有唯一性特点的情况下,建立唯一索引(unique index)代替普通索引,唯一索引(unique index)查询效率比普通索引查询效率更高,可以大幅提升查询速度。

4.组合索引

     4.1.避免建立两个或以上功能相同索引。例如已经建立字段A、B两个字段的索引,应该避免再建立字段A的单独索引。两个索引之间,对相同的查询都会起到相同的作用。建立两个功能相同的索引,反而会容易引起数据库产生错误的查询计划,降低查询效率。

     4.2.选择正确的组合索引字段顺序,最常用的查询字段和选择性、区分度较高的字段,应该作为索引的前导字段使用。

        假设存在组合索引it1c1c2(c1,c2),查询语句select * from t1 where c1=1 and c2=2能够使用该索引。查询语句select * from t1 where c1=1也能够使用该索引。但是,查询语句select * from t1 where c2=2不能够使用该索引,因为没有组合索引的引导列,即,要想使用c2列进行查找,必需出现c1等于某值。

     4.3.合适的字段数,组合索引的字段数不适宜较多,较多的组合索引字段数会降低索引查询效率,组合索引字段数应不多于3个,如业务特点需要建立多字段的组合主键例外。

    关于一个B-Tree索引的例子:

       假设有如下一个表:

        CREATE TABLE People (

           last_name varchar(50)    not null,

           first_name varchar(50)    not null,

           dob        date           not null,

           gender     enum('m', 'f') not null,

           key(last_name, first_name, dob)

        );

       其索引包含表中每一行的last_name、first_name和dob列。其结构大致如下:

       索引存储的值按索引列中的顺序排列。可以利用B-Tree索引进行全关键字、关键字范围和关键字前缀查询,当然,如果想使用索引,你必须保证按索引的最左边前缀(leftmost prefix of the index)来进行查询。

        (1)匹配全值(Match the full value):对索引中的所有列都指定具体的值。例如,上图中索引可以帮助你查找出生于1960-01-01的Cuba Allen。

        (2)匹配最左前缀(Match a leftmost prefix):你可以利用索引查找last name为Allen的人,仅仅使用索引中的第1列。

        (3)匹配列前缀(Match a column prefix):例如,你可以利用索引查找last name以J开始的人,这仅仅使用索引中的第1列。

        (4)匹配值的范围查询(Match a range of values):可以利用索引查找last name在Allen和Barrymore之间的人,仅仅使用索引中第1列。

        (5)匹配部分精确而其它部分进行范围匹配(Match one part exactly and match a range on another part):可以利用索引查找last name为Allen,而first name以字母K开始的人。

        (6)仅对索引进行查询(Index-only queries):如果查询的列都位于索引中,则不需要读取元组的值。

       由于B-树中的节点都是顺序存储的,所以可以利用索引进行查找(找某些值),也可以对查询结果进行ORDER BY。当然,使用B-tree索引有以下一些限制:

        (1)查询必须从索引的最左边的列开始。关于这点已经提了很多遍了。例如你不能利用索引查找在某一天出生的人。

        (2)不能跳过某一索引列。例如,你不能利用索引查找last name为Smith且出生于某一天的人。

        (3)存储引擎不能使用索引中范围条件右边的列。例如,如果你的查询语句为WHERE last_name="Smith" AND first_name LIKE 'J%' AND dob='1976-12-23',则该查询只会使用索引中的前两列,因为LIKE是范围查询。

    另一个例子:

        CREATE TABLE `friends` (

         `id` int(10) unsigned NOT NULL AUTO_INCREMENT,

          `uid` bigint(20) unsigned NOT NULL DEFAULT '0',

          `fuid` bigint(20) unsigned NOT NULL DEFAULT '0',

          `fname` varchar(50) NOT NULL DEFAULT '',

          `fpicture` varchar(150) NOT NULL DEFAULT '',

          `fsex` tinyint(1) NOT NULL DEFAULT '0',

          `status` tinyint(1) NOT NULL DEFAULT '0',

          PRIMARY KEY (`id`),

          KEY `uid_fuid` (`uid`,`fuid`)

        ) ENGINE=MyISAM DEFAULT CHARSET=gbk;

 

 下一个

5.覆盖索引(Covering Indexes)

    如果索引包含满足查询的所有数据,就称为覆盖索引。覆盖索引是一种非常强大的工具,能大大提高查询性能。只需要读取索引而不用读取数据有以下一些优点:

     (1)索引项通常比记录要小,所以MySQL访问更少的数据;

     (2)索引都按值的大小顺序存储,相对于随机访问记录,需要更少的I/O;

     (3)大多数据引擎能更好的缓存索引。比如MyISAM只缓存索引。

     (4)覆盖索引对于InnoDB表尤其有用,因为InnoDB使用聚集索引组织数据,如果二级索引中包含查询所需的数据,就不再需要在聚集索引中查找了。

    注意:覆盖索引不能是任何索引,只有B-TREE索引存储相应的值。而且不同的存储引擎实现覆盖索引的方式都不同,并不是所有存储引擎都支持覆盖索引(Memory和Falcon就不支持)。

     对于索引覆盖查询(index-covered query),使用EXPLAIN时,可以在Extra一列中看到“Using index”

        CREATE TABLE `friends` (

          `id` int(10) unsigned NOT NULL AUTO_INCREMENT,

          `uid` bigint(20) unsigned NOT NULL DEFAULT '0',

          `fuid` bigint(20) unsigned NOT NULL DEFAULT '0',

          `fname` varchar(50) NOT NULL DEFAULT '',

          `fpicture` varchar(150) NOT NULL DEFAULT '',

          `fsex` tinyint(1) NOT NULL DEFAULT '0',

          `status` tinyint(1) NOT NULL DEFAULT '0',

          PRIMARY KEY (`id`),

          KEY `uid_fuid` (`uid`,`fuid`)

        ) ENGINE=MyISAM DEFAULT CHARSET=gbk;

6.排序

     MySQL中,有两种方式生成有序结果集:

     a. filesort            糟糕

     b. Index排序            好

什么时候使用Index排序?

   当索引的顺序与ORDER BY中的列顺序相同且所有的列是同一方向(全部升序或者全部降序)时,可以使用索引来排序。其它情况都会使用filesort。

什么时候使用filesort?

    当MySQL不能使用Index排序时,就会利用自己的排序算法(快速排序算法)在内存(sort buffer)中对数据进行排序,如果内存装载不下,它会将磁盘上的数据进行分块,再对各个数据块进行排序,然后将各个块合并成有序的结果集(实际上就是外排序)。

    当对连接操作进行排序时,如果ORDER BY仅仅引用第一个表的列,MySQL对该表进行filesort操作,然后进行连接处理,此时,EXPLAIN输出“Using filesort”;

    否则,MySQL必须将查询的结果集生成一个临时表,在连接完成之后进行filesort操作,此时,EXPLAIN输出“Using temporary;Using filesort”。

    通过索引优化来实现MySQL的ORDER BY语句优化例子:

     1、ORDER BY的索引优化。如果一个SQL语句形如:

        SELECT [column1],[column2],…. FROM [TABLE] ORDER BY [sort];

       在[sort]这个栏位上建立索引就可以实现利用索引进行order by 优化。

     2、WHERE + ORDER BY的索引优化,形如:

        SELECT [column1],[column2],…. FROM [TABLE] WHERE [columnX] = [value] ORDER BY [sort];

       建立一个联合索引(columnX,sort)来实现order by 优化。

       注意:如果columnX对应多个值,如下面语句就无法利用索引来实现order by的优化

        SELECT [column1],[column2],…. FROM [TABLE] WHERE [columnX] IN ([value1],[value2],…) ORDER BY[sort];

     3、WHERE+ 多个字段ORDER BY

        SELECT * FROM [table] WHERE uid=1 ORDER x,y LIMIT 0,10;

       建立索引(uid,x,y)实现order by的优化,比建立(x,y,uid)索引效果要好得多。

     MySQL Order By不能使用索引来优化排序的情况:

     1、对不同的索引键做 ORDER BY :(key1,key2分别建立索引)

        SELECT * FROM t1 ORDER BY key1, key2;

     2、用于where语句的索引和ORDER BY 的不是同一个:(key1,key2分别建立索引)

        SELECT * FROM t1 WHERE key2=constant ORDER BY key1;

     3、同时使用了 ASC 和 DESC:(key_part1,key_part2建立联合索引),通过where语句将order by中索引列转为常量,则除外

        SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 ASC;

     4、如果在WHERE或ORDER BY的栏位上应用表达式(函数)时,则无法利用索引来实现order by的优化

        SELECT * FROM t1 ORDER BY YEAR(logindate) LIMIT 0,10;

     5、检查的行数过多,且没有使用覆盖索引

     6、where语句中使用了条件查询

7.关于group by或distinct

    7.1.尽量只对存在索引的字段进行group by或distinct。当group by 不能使用index 时mysql有两种处理方法:临时表和filesort。

     7.2.在group by 语句中mysql会自动order,如果不需要可使用order by null来禁止自动的order。

8.关于索引失效

     8.1.避免对索引字段计算

     8.2.避免使用索引列值是否可为空的索引,如果索引列值可以是空值,在SQL语句中那些要返回NULL值的操作,将不会用到索引。

     8.3.相同的索引列不能互相比较,这将会启用全表扫描,如tab1上存在索引idx_col1_col2(col1,col2),其中col1和col2都是int型。则查询语句SELECT * FROM tab1 WHERE col1>col2;是不会使用索引的。

     8.4.避免使用存在潜在的数据类型转换的索引。潜在的数据转换,查询条件中是指由于等式两端的数据类型不一致。例如索引字段使用的是数字类型,而条件等式的另一端数据类型是字符类型,数据库将会对其中一端进行数据类型转换,数据类型的转换会让索引的作用失效,令数据库选择其他的较为低效率的访问路径。

     8.5.使用索引列作为条件进行查询时,需要避免使用或者!=等判断条件。如确实业务需要,使用到不等于符号,需要在重新评估索引建立,避免在此字段上建立索引,改由查询条件中其他索引字段代替。

      a)尽量避免负向查询:NOT、!=、、!、NOT EXISTS、NOT IN、NOT LIKE,避免%前模糊查询

      b)WHERE条件中的范围查询(IN、BETWEEN、、>=)会导致后面的条件使用不了索引。

     8.6.使用索引列作为条件进行范围查询时,应该避免较大范围取值。

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
您什么时候应该使用复合索引与多个单列索引?您什么时候应该使用复合索引与多个单列索引?Apr 11, 2025 am 12:06 AM

在数据库优化中,应根据查询需求选择索引策略:1.当查询涉及多个列且条件顺序固定时,使用复合索引;2.当查询涉及多个列但条件顺序不固定时,使用多个单列索引。复合索引适用于优化多列查询,单列索引则适合单列查询。

如何识别和优化MySQL中的慢速查询? (慢查询日志,performance_schema)如何识别和优化MySQL中的慢速查询? (慢查询日志,performance_schema)Apr 10, 2025 am 09:36 AM

要优化MySQL慢查询,需使用slowquerylog和performance_schema:1.启用slowquerylog并设置阈值,记录慢查询;2.利用performance_schema分析查询执行细节,找出性能瓶颈并优化。

MySQL和SQL:开发人员的基本技能MySQL和SQL:开发人员的基本技能Apr 10, 2025 am 09:30 AM

MySQL和SQL是开发者必备技能。1.MySQL是开源的关系型数据库管理系统,SQL是用于管理和操作数据库的标准语言。2.MySQL通过高效的数据存储和检索功能支持多种存储引擎,SQL通过简单语句完成复杂数据操作。3.使用示例包括基本查询和高级查询,如按条件过滤和排序。4.常见错误包括语法错误和性能问题,可通过检查SQL语句和使用EXPLAIN命令优化。5.性能优化技巧包括使用索引、避免全表扫描、优化JOIN操作和提升代码可读性。

描述MySQL异步主奴隶复制过程。描述MySQL异步主奴隶复制过程。Apr 10, 2025 am 09:30 AM

MySQL异步主从复制通过binlog实现数据同步,提升读性能和高可用性。1)主服务器记录变更到binlog;2)从服务器通过I/O线程读取binlog;3)从服务器的SQL线程应用binlog同步数据。

mysql:简单的概念,用于轻松学习mysql:简单的概念,用于轻松学习Apr 10, 2025 am 09:29 AM

MySQL是一个开源的关系型数据库管理系统。1)创建数据库和表:使用CREATEDATABASE和CREATETABLE命令。2)基本操作:INSERT、UPDATE、DELETE和SELECT。3)高级操作:JOIN、子查询和事务处理。4)调试技巧:检查语法、数据类型和权限。5)优化建议:使用索引、避免SELECT*和使用事务。

MySQL:数据库的用户友好介绍MySQL:数据库的用户友好介绍Apr 10, 2025 am 09:27 AM

MySQL的安装和基本操作包括:1.下载并安装MySQL,设置根用户密码;2.使用SQL命令创建数据库和表,如CREATEDATABASE和CREATETABLE;3.执行CRUD操作,使用INSERT,SELECT,UPDATE,DELETE命令;4.创建索引和存储过程以优化性能和实现复杂逻辑。通过这些步骤,你可以从零开始构建和管理MySQL数据库。

InnoDB缓冲池如何工作,为什么对性能至关重要?InnoDB缓冲池如何工作,为什么对性能至关重要?Apr 09, 2025 am 12:12 AM

InnoDBBufferPool通过将数据和索引页加载到内存中来提升MySQL数据库的性能。1)数据页加载到BufferPool中,减少磁盘I/O。2)脏页被标记并定期刷新到磁盘。3)LRU算法管理数据页淘汰。4)预读机制提前加载可能需要的数据页。

MySQL:初学者的数据管理易用性MySQL:初学者的数据管理易用性Apr 09, 2025 am 12:07 AM

MySQL适合初学者使用,因为它安装简单、功能强大且易于管理数据。1.安装和配置简单,适用于多种操作系统。2.支持基本操作如创建数据库和表、插入、查询、更新和删除数据。3.提供高级功能如JOIN操作和子查询。4.可以通过索引、查询优化和分表分区来提升性能。5.支持备份、恢复和安全措施,确保数据的安全和一致性。

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.能量晶体解释及其做什么(黄色晶体)
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
3 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

禅工作室 13.0.1

禅工作室 13.0.1

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

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

VSCode Windows 64位 下载

VSCode Windows 64位 下载

微软推出的免费、功能强大的一款IDE编辑器

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),