加盟网站合作二手车做网站的目的

当前位置: 首页 > news >正文

加盟网站合作,二手车做网站的目的,中国百强城市榜单发布2021,dede 手机网站模板MySQL索引 1、索引概述2、 索引的数据结构2.1 BTree索引结构2.2 Hash索引结构2.3 InnoDB选择BTree的原因 3、索引分类4、索引的语法5、SQL性能分析5.1 SQL执行频率5.2 慢查询日志5.3 profile详情5.4 explain执行计划 6、索引使用规则6.1 最左前缀法则6.2 范围查询6.3索引失效情… MySQL索引 1、索引概述2、 索引的数据结构2.1 BTree索引结构2.2 Hash索引结构2.3 InnoDB选择BTree的原因 3、索引分类4、索引的语法5、SQL性能分析5.1 SQL执行频率5.2 慢查询日志5.3 profile详情5.4 explain执行计划 6、索引使用规则6.1 最左前缀法则6.2 范围查询6.3索引失效情况6.4 SQL提示6.5 覆盖索引6.6 前缀索引6.7 单列索引与联合索引 7、索引设计原则 1、索引概述 索引index是帮助MySQL高效获取数据的数据结构有序。在数据之外数据库系统还维护着满足特定查找算法的数据结构这些数据结构以某种方式引用指向数据这样就可以在这些数据结构上实现高级查找算法这种数据结构就是索引。 索引的优点 1- 提高数据检索的效率降低数据库的IO成本 2- 通过索引列对数据进行排序降低数据排序的成本降低CPU的消耗。 索引的缺点 1- 索引列也是要占用空间的。 2- 索引大大提高了查询效率同时却也降低更新表的速度如对表进行INSERT、UPDATE、DELETE时效率降低。 2、 索引的数据结构 MySQL的索引是在存储引擎层实现的不同的存储引擎有不同的结构主要包含以下几种 索引结构描述BTree索引最常见的索引类型大部分引擎都支持BTree索引Hash索引底层数据结构是用哈希表实现的只有精确匹配索引列的查询才有效不支持范围查询R-Tree空间索引空间索引是MySQL引擎的一个特殊索引类型主要用于地理空间数据类型通常很少使用Full-text全文索引是一种通过建立倒排索引快速匹配文档的方式。类似于LuceneSolrES 存储引擎对索引的支持情况 索引InnoDBMyISAMMemoryBTree索引支持支持支持Hash索引不支持不支持支持R-Tree索引不支持支持不支持Full-text5.6版本之后支持支持不支持 2.1 BTree索引结构 BTree的每个节点存储多个key与指针假设key的个数为n则指针的个数为n1。key用于控制范围指针指向下一个节点。 在BTree中所有的元素都会出现在叶子结点且数据只存储在叶子结点所有的叶子结点形成单向链表。非叶子结点不存储数据只起到索引的作用。这就使结点中的指针数量增加树的高度降低。 而MySQL对经典BTree进行了优化增加了一个指向相邻叶子结点的链表指针就形成了带有顺序指针的BTree提高区间访问的性能。 BTree结构示意图 MySQL索引数据结构的BTree
2.2 Hash索引结构 哈希索引就是采用一定的Hash算法将键值换算成新的Hash值映射到对应的槽位上然后存储在Hash表中。 如果两个或多个键值映射到一个相同的槽位上他们就产生了hash冲突也称为hash碰撞可以通过链表来解决。 hash索引在存储的时候是没有顺序的 hash索引特点 1- hash索引只能用于对等比较in不支持范围查询between… 2- 无法利用索引完成排序操作 3- 查询效率高通常只需要一次检索就可以了效率通常要高于BTree索引 由于hash索引在存储的时候是没有顺序的导致特点12。 在MySQL中支持hash索引的是Memory存储引擎而InnoDB中具有自适应Hash功能hash索引是存储引擎根据BTree索引在指定条件下自动构建的。 2.3 InnoDB选择BTree的原因 为什么InnoDB存储引擎选择使用BTree索引结构而不选择二叉树红黑树B-Treehash表 首先要分析二叉树、红黑树、B-Tree存在的问题。 二叉树问题顺序插入时会形成一个链表查询性能大大降低。大数据量情况下层级较深检索速度慢。 红黑树问题虽然解决了二叉树形成链表的问题但本质还是二叉树大数据量情况下层级深检索速度慢。 B-Tree问题在MySQL中每个节点存储在一页中页的大小固定为16kB树节点中不仅存储了键值还存储了数据导致存储的键值减少指针也减少。要保存同样大小的数据只能增加树的高度导致性能降低。 hash表只能满足等值查询不支持范围匹配。无法对数据进行排序操作。 因此可以得到以 下三点 1- 相对于二叉树红黑树BTree层级少搜索效率高。 2- 对于B-Tree无论是叶子结点还是非叶子结点都会保存数据而每个节点是保存在一个页中这样导致一页中存储的键值减少指针跟着减少要保存同样大小的数据只能增加树的高度导致性能降低而BTree在B-Tree的基础上进行优化只在叶子结点上存储数据并且在相邻的叶子结点之间增加指针形成双向链表提高性能。 3- Hash索引只能支持等值操作而BTree还支持范围匹配及排序操作。 3、索引分类 索引主要分为四类 分类含义特点关键字主键索引针对于表中主键创建的索引默认自动创建只能有一个PRIMARY唯一索引避免同一个表中某数据列中的值重复可以有多个UNIQUE常规索引快速定位特定数据可以有多个全文索引全文索引查找的是文本中的关键字而不是比较索引中的值可以有多个FULLTEXT 在InnoDB存储引擎中根据索引的存储形式又可以分为以下两种 分类含义特点聚集索引Clustered Index将数据存储于索引放到一块索引结构的叶子结点保存了行数据必须有而且只有一个二级索引Secondary Index将数据与索引分开存储索引结构的叶子结点关联的是对应的主键可以存在多个 聚集索引选取规则 1- 如果存在主键主键索引就是聚集索引 2- 如果不存在主键将使用第一个唯一UNIQUE索引作为聚集索引 3- 如果没有主键或没有合适的唯一索引则InnoDB会自动生成一个rowid作为隐藏的聚集索引。
4、索引的语法 – 创建索引 – [unique | fulltext]指定索引类型可选 – index_name定义索引名自定义 – index_col创建索引的字段可选多个如果同时指定多个则称为联合索引如果只指定一个则称为单列索引 create [unique | fulltext] index index_name on table_name (index_col,…);– 查看索引 show index from table_name;– 删除索引 – 从 table_name 表中删除 index_name 索引 drop index index_name on table_name;5、SQL性能分析 SQL性能分析主要是为SQL优化做准备因此需要明确要为哪类SQL进行优化。一般而言主要对DQL也就是查询语句这类SQL进行优化对增删改的优化是次要的。 5.1 SQL执行频率 分析SQL执行频率。 MySQL客户端连接成功后通过下面的命令可以提供服务器状态信息 – 查看服务器状态信息 – session指当前会话 – global指定全局 show [session | global] status;通过如下指令可以查看当前数据库的insert、update、delete、select的访问频次 – 查看当前数据库增删改查的访问频次 – Com后面是下划线一个下划线代表一个字符 – insert – com_insert – update – com_update – delete – com_delete – select – comselect show global status like Com______;5.2 慢查询日志 慢查询日志记录了所有执行时间超过指定参数long_query_time单位秒默认10秒的所有SQL语句的日志。 MySQL的慢查询日志默认没有开启需要在MySQL的配置文件/etc/my.cnf中配置如下信息

开启MySQL慢查询日志开关

slow_query_log 1

设置慢日志的时间为2秒SQL语句执行时间超过2秒就会视为慢查询记录慢查询日志

long_query_time 2配置完毕之后重新启动MySQL服务器进行测试查看慢查询日志文件中记录的信息 localhost-slow.log可以知道哪些SQL执行耗时过长针对这些SQL进行优化。 5.3 profile详情 show profiles 能够在做SQL优化时帮助我们了解时间都耗费到哪里去了。通过have_profiling参数能够看到当前MySQL是否支持profile操作 – 查看是否支持profile操作 select have_profiling;默认profiling是关闭的可以通过 set 语句在 session/global 级别开启profiling – 开启profiling set [session | global] profiling 1;在开启profiling后就可以执行一系列业务SQL操作然后通过如下指令查看指令的执行耗时 – 查看每一条SQL的耗时基本情况 show profiles;– 查看指定query_id的SQL语句各个阶段的耗时情况 show profile for query query_id;– 查看指定query_id的SQL语句CPU的使用情况 show profile cpu for query query_id;5.4 explain执行计划 explain 或者 desc 命令获取 MySQL 如何执行 select 语句的信息包括在 select 语句执行过程中表如何连接和连接的顺序。 – 直接在 select 语句之前加上关键字 explain / desc explain select 字段列表 from 表名 where 条件;执行计划会返回很多信息id、select_type、table、partitions、type、possible_keys、key、key_len、ref、rows、filtered、extra下面一一介绍 explain 执行计划各字段含义 idselect 查询的序列号表示查询中执行 select 子句或者是操作表的顺序 id 相同执行顺序从上到下id 不同值越大越先执行。select_type表示 select 的类型常见的取值有 simple 简单表即不使用表连接或者子查询、primary主查询即外层的查询、unionunion中的第二个或者后面的查询语句、subqueryselect / where 之后包含了子查询等。type表示连接类型性能由好到差的连接类型为null、system、const、eq_ref、ref、range、index、all。possible_key显示可能应用在这张表上的索引一个或多个。key实际使用的索引如果为null则没有使用索引。key_len表示索引中使用的字节数该值为索引字段最大可能长度并非实际使用长度在不损失精确性的前提下长度越短越好。rowsMySQL认为必须要执行查询的行数在InnoDB引擎的表中是一个估计值可能并不总是准确的。filtered表示返回结果的行数站需要读取行数的百分比filtered的值越大越好。extra额外信息。 6、索引使用规则 6.1 最左前缀法则 如果索引了多列联合索引要遵循最左前缀法则。 最左前缀法则查询从索引的最左列开始并且不跳过索引中的列。如果跳跃某一列索引将部分失效后面的字段索引失效。 要满足最左前缀法则只需要最左列存在不关心位置。 举例 若创建如下联合索引 – 在 user 表中根据 nameageaddress 这三个字段创建联合索引 – 最左列为 name 要使用该索引则需要存在 name 的条件 create index idx_user_name_age_address on user(name, age, address);那么不同的查询语句使用 idx_user_name_age_address 索引有多种情况 – 使用 idx_user_name_age_address 索引并且使用到了索引的全字段 select * from user where name 张三 and age 18 and address 北京;– 使用 idx_user_name_age_address 索引但是没有使用address字段因为sql语句中没有 address 条件 select * from user where name 张三 and age 18;– 使用 idx_user_name_age_address 索引只使用了 name 字段因为sql语句中没有 age 和 address 条件 select * from user where name 张三;– 使用 idx_user_name_age_address 索引但只使用了 name 字段因为跳跃了 age 这一列使后面的字段失效 select * from user where name 张三 and address 北京;– 使用 idx_user_name_age_address 索引并且使用了全字段虽然 name 位置不在第一个但是存在 name 字段条件 select * from user where age 18 and address 北京 and name 张三;– 未使用 idx_user_name_age_address 索引因为不满足最左前缀法则条件没有 name 字段。 select * from user where age 18 and address 北京;6.2 范围查询 联合索引中出现范围查询范围查询右侧的列索引失效。 举例 若创建如下联合索引 – 在 user 表中根据 jobageaddress 这三个字段创建联合索引 – 最左列为 job要使用该索引则需要存在 job 的条件 create index idx_user_job_age_address on user(job, age, address);分析如下 sql 语句的索引使用情况 – 使用 idx_user_job_age_address 索引但未使用 address 字段这是因为 age 25 为范围查询范围查询右侧的列索引失效 select * from user where job 程序员 and age 25 and address 北京;– 使用 idx_user_job_age_address 索引并且使用了所有的字段这是因为 age 25 规避了范围查询 select * from user where job 程序员 and age 25 and address 北京;从上面的案例中可以受到启发在项目开发中在满足业务需求的情况下尽量使用 而不是用 。 6.3索引失效情况 索引列运算不要在索引列上进行运算操作否则索引将失效。 字符串不加引号字符串类型字段使用时不加引号索引将失效。 模糊查询如果仅仅是尾部模糊匹配索引不会失效。如果是头部模糊匹配索引失效。 or连接的条件用 or 分割开的条件如果 or 前的条件中的列有索引而后面的列中没有索引那么涉及的索引都不会被用到。只有 or 两侧都有索引时才会生效。 数据分布影响如果MySQL评估使用索引比全表扫描慢则不使用索引。 6.4 SQL提示 SQL 提示是优化数据库的一个重要手段简单来说就是在SQL语句中加入一些人为的提示来达到优化操作的目的。这个提示是指开发者给MySQL的提示。 语法 在表后面加 use/ignore/force index(指定index) – use index建议使用指定索引但MySQL可以根据实际情况分析是否使用该索引 explain select * from user use index(idx_user_name) where name 张三;– ignore index: 忽略索引不使用指定索引 explain select * from user ignore index(idx_user_name) where name 张三;– force index强制使用指定索引 explain select * from user force index(idx_user_name) where name 张三;6.5 覆盖索引 尽量使用覆盖索引查询使用了索引并且需要返回的列在该索引中已经全部能够找到。减少使用 select * 的情况。 覆盖索引是研究返回字段对查询性能的影响。 研究如下几条 SQL他们的 where 条件相同但返回的字段不同 前提创建了如下几个索引 – 在 user 表上给 jobagegender 字段创建了联合索引 idx_user_job_age_gender create index idx_user_job_age_gender on user(job, age, gender); – 在 user 表上给 name 字段创建索引 idx_user_name create index idx_user_name on user(name);分析 SQL – 执行计划 extra 字段提示using where; using index – 因为建立了 jobagegender 这三个字段联合索引联合索引中包含了查询返回的 id 和 job 数据只需要一次二级查询即可。 explain select id, job from user where job 程序员 and age 25 and gender 1;– 执行计划 extra 字段提示using where; using index – 因为建立了 jobagegender 这三个字段联合索引联合索引中包含了查询返回的 idjobagegender 数据只需要一次二级查询即可。 explain select id, job, age, gender from user where job 程序员 and age 25 and gender 1;– 执行计划 extra 字段提示using index condition – 虽然建立了 jobagegender 这三个字段联合索引但是索引列中不包含 name 字段查询返回 name 字段需要根据 id 进行回表查询性能降低。 explain select id, job, age, gender, name from user where job 程序员 and age 25 and gender 1;– 执行计划 extra 字段提示using index condition – * 通配表中所有字段而 idx_user_job_age_gender 索引中只包含 idjobagegender数据因此需要回表查询。 explain select * from user where job 程序员 and age 25 and gender 1;知识补充 using index condition查找使用了索引但是需要回表查询数据。 using where; using index查找使用了索引但是需要的数据都在索引列中能找到所以不需要回表查询数据。 using where; using index 的性能高于 using index condition 6.6 前缀索引 当字段类型为字符串varchartext等时有时候需要索引很长的字符串这会让索引变得很大查询时浪费大量的磁盘IO影响查询效率。此时可以只将字符串的一部分前缀建立索引这样可以大大节约索引空间从而提高索引效率。 建立前缀索引的语法 – idx_xxx自定义索引名 – table_name表名 – column字段一般为varchartext等类型 – n前缀长度截取字符串的长度 create index idx_xxx on table_name(column(n))如何确定前缀 可以根据索引的选择性来决定而选择性是指不重复的索引值基数和数据表的记录总数的比值索引选择性越高则查询效率越高唯一索引的选择性是1这是最好的索引选择性性能也是最好的。 可以通过下面的 sql 来计算选择性; – 这里以 user 表中的 email 字段为例使用 email 的全部字符计算选择性 select count(distinct email) / count() from user; – 截取 email 字段的前5个字符计算选择性 select count(distinct substring(email, 1, 5)) / count() from user;6.7 单列索引与联合索引 单列索引即一个索引只包含单个列。 联合索引即一个索引包含了多个列。 在业务场景中如果存在多个查询条件考虑针对于查询字段建立索引时建议建立联合索引而非单列索引。 多条件联合查询时MySQL优化器会评估哪个字段的索引效率更高会选择该索引完成本次查询。 7、索引设计原则 针对于数据量较大且查询比较频繁的表建立索引。针对于常作为查询条件where、排序order by、分组group by操作的字段建立索引。尽量选择区分度高的列作为索引尽量建立唯一索引区分度越高使用索引的效率越高。如果是字符串类型的字段字段的长度较长可以针对于字段的特点建立前缀索引。尽量使用联合索引减少使用单列索引查询时联合索引很多时候可以覆盖索引节省存储空间避免回表查询提高查询效率。要控制索引的数量索引并不是多多益善索引越多维护索引结构的代价也越大会影响增删改的效率。如果索引列不能存储 NULL 值请在创建表时使用 NOT NULL 约束它。当优化器知道每列是否包含 NULL 值时它可以更好地确定哪个索引最有效地用于查询。