2026/4/18 10:03:25
网站建设
项目流程
可信网站验证,松江 网站建设公司,网站建设数据处理,网站关键词优化遇到的情况和解决方法目录
1.什么是索引 1.1 索引的数据结构 1.1.1 Hash表1.1.2 二叉查找树1.1.3 平衡二叉树1.1.4 B树1.1.5 B树 2.索引的优缺点3.索引的使用场景4.索引的分类 4.1 主键索引4.2 唯一索引4.3 单值索引(单列索引)4.4 复合索引(组合索引)4.5 普通索引4.6 全文索引4.7 空间索引4.8 前缀…目录1.什么是索引1.1 索引的数据结构1.1.1 Hash表1.1.2 二叉查找树1.1.3 平衡二叉树1.1.4 B树1.1.5 B树2.索引的优缺点3.索引的使用场景4.索引的分类4.1 主键索引4.2 唯一索引4.3 单值索引(单列索引)4.4 复合索引(组合索引)4.5 普通索引4.6 全文索引4.7 空间索引4.8 前缀索引4.9 覆盖索引5.索引测试6.性能分析6.1 Mysql常见瓶颈6.2 Explain6.3 explain重要字段6.3.1 id6.3.2 select_type6.3.3 type6.3.4 possible_key6.3.5 keykey_len:6.3.6 ref6.3.7 rows6.3.8 extra7.查询优化7.1 索引失效7.2 排序优化7.3 优化案例7.3.1 单表查询优化7.3.2 关联查询优化7.3.3 分组优化8.慢查询日志8.1 简介8.2 使用1.什么是索引索引是帮助MySQL高效获取数据的数据结构MySQL在存储数据之外数据库系统中还维护着满足特定查找算法的数据结构这些数据结构以某种引用(指向)表中的数据,这样我们就可以通过数据结构上实现的高级查找算法来快速找到我们想要的数据。而这种数据结构就是索引。1.1 索引的数据结构1.1.1 Hash表在java中的HashMapTreeMap是Hash表结构以键值对的方式存储数据使用Hash表存储表数据Key可以存储索引列Value可以存储行记录或者行磁盘地址。Hash在等值查询效率高时间复杂度是O(1),但是不支持范围快速查找范围查找时只能通过扫描全表方式不适合经常需要查找和范围查找的数据库索引使用1.1.2 二叉查找树二叉树存储的值是以key-value结构存储二叉树特点每个节点最多有2个分叉左小右大。可以保证每次查找减少IO次数但是会出现一直向右下插或者左下插入比如接下来要插入的数据是182022等 这样就非常难受。这种数据结构不稳定1.1.3 平衡二叉树平衡二叉树采用的是二分法的思维它最主要的特征是树的左右两个子树的层级最多相差1它的时间复杂度是O(log2 n)存在问题当插入的数据过多时树会很高这样每层节点的数量就会很多。每个节点读取都对应这一次磁盘的IO操作这样查询性能就会很差。1.1.4 B树MySQL的数据是存储在磁盘文件中的查询处理数据时需要先把磁盘中的数据加载到内存中磁盘IO操作非常耗时需要我们去减少IO操作那么就需要就减少树的高度B树是一种多叉平衡查找树每个结点存储M/2到M个关键字非叶子结点存储指向关键字范围的子结点所有关键字在整颗树中出现且只出现一次非叶子结点可以命中1.定义任意非叶子结点最多只有M个儿子且M22.根结点的儿子数为[2, M]3.除根结点以外的非叶子结点的儿子数为[M/2, M]4.每个结点存放至少M/2-1取上整和至多M-1个关键字至少2个关键字5.非叶子结点的关键字个数指向儿子的指针个数-16.非叶子结点的关键字K[1], K[2], …, K[M-1]且K[i] K[i1]7.非叶子结点的指针P[1], P[2], …, P[M]其中P[1]指向关键字小于K[1]的子树P[M]指向关键字大于K[M-1]的子树其它P[i]指向关键字属于(K[i-1], K[i])的子树8.所有叶子结点位于同一层B树的特点1.关键字集合分布在整颗树中2.任何一个关键字出现且只出现在一个结点中3.搜索有可能在非叶子结点结束4.其搜索性能等价于在关键字全集内做一次二分查找5.自动层次控制1.1.5 B树使用B树构建索引B树和B树最主要的区别在于非叶子节点是否存储数据的问题。B树在B-树基础上为叶子结点增加链表指针所有关键字都在叶子结点中出现非叶子结点作为叶子结点的索引B树总是到叶子结点才命中B的搜索与B-树也基本相同区别是B树只有达到叶子结点才命中B树的特点1.所有关键字都出现在叶子结点的链表中稠密索引且链表中的关键字恰好是有序的2.不可能在非叶子结点命中3.非叶子结点相当于是叶子结点的索引稀疏索引叶子结点相当于是存储关键字数据的数据层4.更适合文件索引系统2.索引的优缺点优点提高数据的检索效率降低数据库的IO成本通过索引对数据进行排序降低了数据排序的成本降低了CPU的消耗被索引的列会自动进行排序包括【单列索引】和【组合索引】只是组合索引的排序要复杂一些。如果按照索引列的顺序进行排序对应order by语句来说效率就会提高很多缺点索引会占据磁盘的空间索引虽然会提高查询效率但是会降低更新表的效率。比如每次对表进行增删改操作MySQL不仅要保存数据还有保存或者更新对应的索引文件。3.索引的使用场景哪些情况需要创建索引1.主键自动建立唯一索引2.频繁作为查询条件的字段应该创建索引(where后面的语句)3.查询中与其他表关联的字段外键关系建立索引4.多字段查询下倾向创建组合索引5.查询中排序的字段排序字段若通过索引去访问将大大提高排序速度6.查询中统计或者分组字段哪些情况不需要创建索引1.表记录太少2.经常增删改的表3.where条件里用不到的字段不建立索引4.索引的分类4.1 主键索引表中的列设定为主键后数据库会自动建立主键索引索引列中的值必须是唯一的不允许有空值单独创建和删除主键索引的语法创建alter table 表名 add primary key(字段)删除alter table 表名 drop primary keyCREATE TABLE users (id INT AUTO_INCREMENT,username VARCHAR(50) NOT NULL,email VARCHAR(100) NOT NULL,PRIMARY KEY (id));在这个例子中id列被定义为主键MySQL会自动为这个列创建一个主键索引。4.2 唯一索引表中的列创建了唯一约束时数据库会自动建立唯一索引索引列中的值必须是唯一的但是允许为空值。单独创建和删除唯一索引的语法创建alter table 表名 add unique 索引名(字段)或create unique index 索引名 on 表名(字段)删除drop index 索引名 on 表名CREATE TABLE users (id INT AUTO_INCREMENT,username VARCHAR(50) NOT NULL,email VARCHAR(100) NOT NULL,PRIMARY KEY (id),UNIQUE INDEXunique_email(email));在这里email列有一个唯一索引确保每个电子邮件地址在表中是唯一的。4.3 单值索引(单列索引)一个索引只包含单个列一个表可以有多个单值索引。1.建表时可随表一起建立单值索引2.单独创建和删除单值索引创建alter table 表名 add index 索引名(字段)或 create index 索引名 on 表名(字段)删除drop index 索引名 on 表名4.4 复合索引(组合索引)一个索引包含多个列1.建表时可随表一起建立复合索引2.单独创建和删除复合索引创建create index 索引名 on 表名(字段1字段2)或 alter table 表名 add index 索引名(字段1字段2)删除drop index 索引名 on 表名CREATE INDEX idx_name_date ON events (name, date);这个例子创建了一个组合索引包含events表的name和date两个列可以加速同时涉及这两个字段的查询。4.5 普通索引最基本的索引类型没有唯一性的限制主要用于提高查询性能。一个表可以有多个普通索引。CREATE INDEX idx_username ON users (username);这个例子为users表的username列创建了一个普通索引用来加速基于username的查询4.6 全文索引专门用于全文搜索的索引。只有在MyISAM和InnoDB从MySQL 5.6版本开始支持存储引擎的CHAR、VARCHAR或TEXT类型列上才能创建全文索引。CREATE FULLTEXT INDEX ft_idx_content ON articles (content);在这个例子中articles表的content列上创建了一个全文索引用于全文搜索。4.7 空间索引用于空间数据类型的索引如MySQL的地理数据类型GEOMETRY。这种索引类型主要用于空间数据查询只有MyISAM存储引擎支持空间索引。CREATE SPATIAL INDEX sp_idx_location ON parks (location);在这里parks表的location列是一个地理数据类型创建了一个空间索引用于地理位置查询。4.8 前缀索引对于文本类的长字段可以创建前缀索引来提高索引效率只索引字段的前面一部分字符。CREATE INDEX idx_text_prefix ON articles (content(100));在这个例子中articles表的content列创建了一个前缀索引只索引了内容的前100个字符。4.9 覆盖索引如果一个索引包含了查询所需的所有数据那么这个索引被称为覆盖索引。查询可以直接通过索引来获取数据无需回表查询。假设有以下查询SELECT username, email FROM users WHERE username john_doe;如果有一个索引CREATE INDEX idx_username_email ON users (username, email);这个索引就是一个覆盖索引因为它包含了查询所需的所有字段username和email无论是返回的数据还是过滤个条件都是索引字段查询可以直接使用索引来获取数据不需要访问表的其他部分。5.索引测试create table person( pid int (11) auto_increment , pname varchar(50) , psex varchar(10), page int(11), sal decimal(7,2), primary key(pid) );6.性能分析6.1 Mysql常见瓶颈SQL中对大量数据进行比较、关联、排序、分组时CPU的瓶颈。实例内存满足不了缓存数据或排序等需要导致产生大量的物理IO查询数据时扫描过多数据行导致查询效率低。6.2 Explain使用EXPLAIN关键字可以模拟优化器执行sQL查询语句,从而知道MYSQL是如何处理SQL语句的。可以用来分析查询语句或是表的结构的性能瓶颈。其作用:1.表的读取顺序2.哪些索引可以使用3.数据读取操作的操作类型4.哪些索引被实际使用5.表之间的引用6.每张表有多少行被优化器查询使用explain sql语句6.3 explain重要字段6.3.1 idselect查询的序列号表示查询中执行select子句或操作表的顺序。id相同时执行顺序由上至下先从t1表里去再去t2表里取最后再去t3表里取id不同如果是子查询id的序号会递增id值越大优先级越高则先被执行。id相同和不同都存在时id相同的可以理解为一组从上到下顺序执行所有组中id值越大优先级越高越先执行derived是s3能够临时表里查出的数据6.3.2 select_type查询的类型常见的值有SIMPLE:简单的select查询查询中不包含子查询或者UNIONPRIMARY查询中若包含任何复杂的子部分最外查询则被标记为PrimaryDERIVED在FROM列表中包含的子查询被标记为DERIVED(衍生)Mysql会递归执行这些子查询把结果放在临时表里。最外面的查询会被标记为primary子查询被标记为derivedSUBQUERY在select或where列表中包含了子查询。6.3.3 type访问类型排序all index range ref eq_ref const system从最好到最差依次是 system const eq_ref ref rangeindex All,一般来说最好保证查询能达到range级别最好能达到refAll将遍历全表以找到匹配的行System表里只有一行记录(等于系统表)这是const类型的特列平时不会出现这个可以忽略不计。Const表示通过索引一次就找到了const用于比较primary key(主键索引) 或者unique(唯一索引)。因为只匹配一行数据所以很快如将主键置于where列表中Mysql就能把该查询转换成一个常量eq_ref:唯一性索引扫描对于每个索引键表中只有一条记录与之匹配。常见于主键或者唯一索引扫描(常用在连表查询)ref非唯一性索引扫描返回匹配某个单独值的所有行。本质上也是一种索引访问它返回所有匹配某个单独值的行然而它可能会找到多个符合条件得行所以他应该属于查找和扫描得混合体。range只检索给定范围的行使用一个索引来选择行。key列显示使用了哪个索引一般就是在你的where语句中出现了between、、、in等的查询这种范围扫描索引比全表扫描要好因为它只需要开始于索引的某一点而结束于另一点不用扫描全部索引。(使用索引进行范围查询)indexindex和all的区别在于index类型只遍历索引树。这通常比all快因为索引文件通常比数据文件小也就是说虽然all和index都是读全表但是all读的是存数据的表index读取的是索引表all从硬盘中读取数据index 是从索引中读取的6.3.4 possible_key显示可能应用在这张表中的索引一个或多个查询涉及到的字段上如果存在索引则该索引将会被列出来但不一定会被查询实际使用上。6.3.5 key查询中实际使用的索引如果为null则表示没有使用索引。索引失效key_len:使用索引的字节数数越大 代表使用索引越充分6.3.6 ref显示索引的哪一列被使用了哪些列或常量被用于查找索引列上的值t3的查询运用到了t2里面id这个列6.3.7 rowsrows列显示MySQL认为它执行查询时必须查询的行数一般越少越好。删除索引 进行查询用索引查询6.3.8 extra一些常见的重要的额外信息Using filesortMySQL无法利用索引完成的排序操作称为“文件排序”Using temporaryMySQL在对查询结果排序时使用临时表常见于排序order by 和分组查询group byUsing index表示索引被用来执行索引键值的查找避免访问了表的数据行效率不错Using where表示使用了where过滤7.查询优化7.1 索引失效1.合最佳左前缀法则如果索引了多列要遵循最左前缀法则指的是查询从索引的最左前列开始并且不跳过索引中的列。正常符合法则时不符合时2.不在索引列上做任何计算、函数操作会导致索引失效而转向全表扫描做函数操作会导致失效3.存储引擎不能使用索引中范围条件右边的列使用范围条件后后面的列的索引会失效4.MySQL在使用不等于时无法使用索引会导致全表扫描使用不等于时 会导致索引失效5.is null 可以使用索引但是is not null 无法使用索引is null 可以使用素引is not null 不能使用索引6.like 以通配符开头会使索引失效导致全表扫描通配符在前面索引失效通配符在后面索引不失效7.字符串不加单引号索引会失效8.使用or连接时索引失效9.数据库和表的字符集统一使用utf8mb4统一使用utf8mb4( 5.5.3 版本以上支持 ) 兼容性更好统一字符集可以避免由于字符集转换产生的乱码。不同的 字符集 进行比较前需要进行 转换 会造成索引失效。建议1.对于单值索引尽量选择针对当前查询字段过滤性更好的索引。2.对于组合索引当前where查询中过滤性更好的字段在索引字段顺序中位置越靠前越好。3.对于组合索引尽量选择能够包含在当前查询中where子句中更多字段的索引。4.尽可能通过分析统计信息和调整query的写法来达到选择合适索引的目的。7.2 排序优化1.尽量避免使用Using FileSort方式排序2.order by 语句使用索引最左前列或者使用where子句与order by 子句条件组合满足索引最左前列3.where子句中如果出现索引范围查询会导致order by 索引失效7.3 优化案例7.3.1 单表查询优化优化前优化(建索引发现comment是范围查询导致views索引失效)把comment踢出索引优化成功7.3.2 关联查询优化内连接时mysql.会自动把小结果集的选为驱动表所以大表的字段最好加上索引。左外连接时左表会全表扫描所以右边大表字段最好加上索引右外连接同理。我们最好保证被驱动表上的字段建立了索引。优化前(被驱动表是book)优化后7.3.3 分组优化优化前优化后8.慢查询日志8.1 简介MysQL 的慢查询日志是MySQL提供的一种日志记录他用来记录在MysQL中响应时间超过阀值的语句具体指运行时间超过long_query_time值的SQL则会被记录到慢查询日志中。可以由它来查看哪些sQL超出了我们最大忍耐时间值。8.2 使用默认情况下MySQL数据库没有开启慢查询日志需要手动设置参数查看是否开启show variables like %slow_query_log%开启日志set global slow_query_log 1设置时间set global long_query_log 1查看时间show variables like long_query_time%查看超时的sql记录日志Mysql的数据文件夹下注意:非调优场景下一般不建议启动改参数慢查询日志支持将日志记录写入文件开启慢查询日志会或多或少带来—定的性能影响。