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

网站建设佰首选金手指二六wordpress 360急速模式打不开

网站建设佰首选金手指二六,wordpress 360急速模式打不开,合肥seo优化外包公司,中国庆阳MySQL进阶MySQL体系结构存储引擎存储引擎特点InnoDB逻辑存储结构MyISAMMemory存储引擎选择索引索引结构二叉树B-TreeBTreeHash索引分类索引语法SQL性能分析工具SQL执行频率慢查询日志profile详情explain索引使用联合索引索引失效情况SQL提示覆盖索引前缀索引单列索引与联合索引… MySQL进阶MySQL体系结构存储引擎存储引擎特点InnoDB逻辑存储结构MyISAMMemory存储引擎选择索引索引结构二叉树B-TreeBTreeHash索引分类索引语法SQL性能分析工具SQL执行频率慢查询日志profile详情explain索引使用联合索引索引失效情况SQL提示覆盖索引前缀索引单列索引与联合索引索引设计原则SQL优化插入数据大批量数据插入主键优化order by优化group by优化limit优化count优化update优化MySQL体系结构 连接层 最上层是一些客户端和链接服务主要完成一些类似于连接处理授权认证及相关的安全方案。服务器也会为安全接入的每个客户验证它所具有的操作权限。服务层 第二层架构主要完成大多数的核心服务功能如SQL接口并完成缓存的查询SQL的分析和优化部分内置函数的执行所有跨存储引擎的功能也在这层实现如过程函数等。引擎层 存储引擎真正的负责了MySQL中数据的存储和提取服务器通过API和存储引擎进行通信。不同的存储引擎具有不同的功能这样可以根据自己的需要来选取合适的存储引擎。存储层 主要是将数据存储在文件系统之上并完成与存储引擎的交互。 存储引擎 存储引擎就是存储数据、建立索引、更新/查询数据等技术的实现方式 。存储引擎是基于表的而不是基于库的所以存储引擎也可被称为表类型。 所以可以在创建表的时候来指定选择的存储引擎如果没有指定将自动选择默认的存储引擎。 建表时指定存储引擎 CREATE TABLE 表名(字段1 字段1类型 [ COMMENT 字段1注释 ] ,......字段n 字段n类型 [COMMENT 字段n注释 ] ) ENGINE INNODB [ COMMENT 表注释 ] ;查询当前数据库支持的存储引擎 show engines;创建表 my_myisam , 并指定MyISAM存储引擎 create table my_myisam(id int,name varchar(10) ) engine MyISAM ;创建表 my_memory , 指定Memory存储引擎 create table my_memory(id int,name varchar(10) ) engine Memory ;存储引擎特点 InnoDB InnoDB是一种兼顾高可靠性和高性能的通用存储引擎在 MySQL 5.5 之后InnoDB是默认的MySQL 存储引擎。 特点 DML操作遵循ACID模型支持事务行级锁提高并发访问性能支持 外键 FOREIGN KEY约束保证数据的完整性和正确性 文件 xxx.ibdxxx代表的是表名innoDB引擎的每张表都会对应这样一个表空间文件存储该表的表结构frm-早期的 、sdi-新版的、数据和索引。 show variables like innodb_file_per_table;如果该参数开启代表对于InnoDB引擎的表每一张表都对应一个ibd文件。 直接打开MySQL的数据存放目录 D:\java\software\mysql-8.0.11-winx64\Data 这个目录下有很多文件夹不同的文件夹代表不同的数据库直接打开itcast文件夹如下 每一个ibd文件就对应一张表比如有一张表 account就有这样的一个account.ibd文件而在这个ibd文件中不仅存放表结构、数据还会存放该表对应的索引信息。 而该文件是基于二进制存储的不能直接基于记事本打开可以使用mysql提供的一个指令 ibd2sdi 通过该指令就可以从ibd文件中提取sdi信息而sdi数据字典信息中就包含该表的表结构。 逻辑存储结构 表空间 : InnoDB存储引擎逻辑结构的最高层ibd文件其实就是表空间文件在表空间中可以包含多个Segment段。段 : 表空间是由各个段组成的 常见的段有数据段、索引段、回滚段等。InnoDB中对于段的管理都是引擎自身完成不需要人为对其控制一个段中包含多个区。区 : 区是表空间的单元结构每个区的大小为1M。 默认情况下 InnoDB存储引擎页大小为16K 即一个区中一共有64个连续的页。页 : 页是组成区的最小单元页也是InnoDB 存储引擎磁盘管理的最小单元每个页的大小默认为 16KB。为了保证页的连续性InnoDB 存储引擎每次从磁盘申请 4-5 个区。行 : InnoDB 存储引擎是面向行的也就是说数据是按行进行存放的在每一行中除了定义表时所指定的字段以外还包含两个隐藏字段(后面会详细介绍)。 MyISAM MyISAM是MySQL早期的默认存储引擎。 特点 不支持事务不支持外键支持表锁不支持行锁访问速度快 文件 xxx.sdi存储表结构信息 xxx.MYD: 存储数据 xxx.MYI: 存储索引 Memory Memory引擎的表数据时存储在内存中的由于受到硬件问题、或断电问题的影响只能将这些表作为临时表或缓存使用。 特点 内存存放hash索引默认 文件 xxx.sdi存储表结构信息 区别及特点 InnoDB引擎与MyISAM引擎的区别 ? InnoDB引擎, 支持事务, 而MyISAM不支持。InnoDB引擎, 支持行锁和表锁, 而MyISAM仅支持表锁, 不支持行锁。InnoDB引擎, 支持外键, 而MyISAM是不支持的。 存储引擎选择 在选择存储引擎时应该根据应用系统的特点选择合适的存储引擎。对于复杂的应用系统还可以根据实际情况选择多种存储引擎进行组合。 InnoDB: 是Mysql的默认存储引擎支持事务、外键。如果应用对事务的完整性有比较高的要求在并发条件下要求数据的一致性数据操作除了插入和查询之外还包含很多的更新、删除操作那么InnoDB存储引擎是比较合适的选择。MyISAM 如果应用是以读操作和插入操作为主只有很少的更新和删除操作并且对事务的完整性、并发性要求不是很高那么选择这个存储引擎是非常合适的。MEMORY 将所有数据保存在内存中访问速度快通常用于临时表及缓存。MEMORY的缺陷就是对表的大小有限制太大的表无法缓存在内存中而且无法保障数据的安全性。 索引 索引index是帮助MySQL 高效获取数据的有序数据结构。在数据之外数据库系统还维护着满足特定查找算法的数据结构这些数据结构以某种方式引用指向原始数据 这样就可以在数据结构上通过高级查找算法快速定位到原始数据。 select * from user where age 45;无索引情况就需要从第一行开始扫描一直扫描到最后一行我们称之为 全表扫描性能很低。 有索引情况如果针对于这张表建立了索引假设索引结构就是二叉树那么也就意味着会对age这个字段建立一个二叉树的索引结构。此时我们在进行查询时只需要扫描三次就可以找到数据了极大的提高的查询的效率。 优点 提高数据检索的效率降低数据库的IO成本通过索引对数据进行排序降低数据排序的成本降低CPU的消耗 缺点 索引也要占用空间索引大大提高了查询效率同时也降低了更新表的速度如对表进行INSERT,UPDATE,DELETE时效率降低 索引结构 MySQL的索引是在存储引擎层实现的不同的存储引擎有不同的索引结构主要包含以下几种 不同的存储引擎对于索引结构的支持情况 二叉树 假如说MySQL的索引结构采用二叉树(一个节点下面最多包含两个节点)的数据结构比较理想的结构如下 如果主键是顺序插入的则会形成一个单向链表结构如下查找17时相当于把整张链表遍历一次 如果选择二叉树作为索引结构会存在以下缺点 顺序插入时会形成一个链表查询性能大大降低。因为一个节点下最多只能包含两个子节点大数据量情况下层级较深检索速度慢。 如果选择红黑树红黑树是一颗自平衡二叉树即使顺序插入数据最终形成的数据结构也是一颗平衡的二叉树,结构如下: 由于红黑树也是一颗二叉树所以也会存在一个缺点 大数据量情况下层级较深检索速度慢。 B-Tree B-Tree是一种多路平衡查找树相对于二叉树B树每个节点可以有多个分支即多叉。以一颗最大度数max-degree为5(5阶)的b-tree为例(即B树每个节点最多存储4个key5个指针) 树的度数指的是一个节点的子节点个数。 可以通过一个数据结构可视化的网站来简单演示一下。 https://www.cs.usfca.edu/~galles/visualization/BTree.html 插入一组数据 100 65 169 368 900 556 780 35 215 1200 234 888 158 90 1000 88 120 268 250 。然后观察一些数据插入过程中节点的变化情况。 特点 5阶的B树每一个节点最多存储4个key对应5个指针。一旦节点存储的key数量到达5就会裂变中间元素向上分裂。在B树中非叶子节点和叶子节点都会存放数据。 BTree BTree是B-Tree的变种以一颗最大度数max-degree为44阶3个key4个指针的btree为例其结构示意图 绿色框框起来的部分是索引部分仅仅起到索引数据的作用不存储数据。红色框框起来的部分是数据存储部分在其叶子节点中要存储具体的数据。 BTree 与 B-Tree相比主要有以下三点区别 所有的数据都会出现在叶子节点。叶子节点形成一个单向链表。非叶子节点仅仅起到索引数据作用具体的数据都是在叶子节点存放的。 通过数据结构可视化的网站来简单演示一下https://www.cs.usfca.edu/~galles/visualization/BPlusTree.html 插入一组数据 100 65 169 368 900 556 780 35 215 1200 234 888 158 90 1000 88 120 268 250 。然后观察一些数据插入过程中节点的变化情况。 MySQL索引数据结构对经典的BTree进行了优化。在原BTree的基础上增加一个指向相邻叶子节点的链表指针就形成了带有顺序指针的BTree提高区间访问的性能利于排序。 Hash 哈希索引就是采用一定的hash算法将键值换算成新的hash值映射到对应的槽位上然后存储在hash表中。 如果两个(或多个)键值映射到一个相同的槽位上他们就产生了hash冲突也称为hash碰撞可以通过链表来解决。 特点 Hash索引只能用于对等比较(in)不支持范围查询between …无法利用索引完成排序操作查询效率高通常(不存在hash冲突的情况)只需要一次检索就可以了效率通常要高于Btree索引 存储引擎支持 在MySQL中支持hash索引的是Memory存储引擎。 而InnoDB中具有自适应hash功能hash索引是InnoDB存储引擎根据BTree索引在指定条件下自动构建的。 为什么InnoDB存储引擎选择使用Btree索引结构 相对于二叉树层级更少搜索效率高对于B-tree无论是叶子节点还是非叶子节点都会保存数据这样导致一页中存储的键值减少指针跟着减少要同样保存大量数据只能增加树的高度导致性能降低相对Hash索引Btree支持范围匹配及排序操作 索引分类 在MySQL数据库将索引的具体类型主要分为以下几类主键索引、唯一索引、常规索引、全文索引。 在InnoDB存储引擎中根据索引的存储形式又可以分为以下两种 聚集索引选取规则: 如果存在主键主键索引就是聚集索引如果不存在主键将使用第一个唯一UNIQUE索引作为聚集索引。如果表没有主键或没有合适的唯一索引则InnoDB会自动生成一个rowid作为隐藏的聚集索引。 聚集索引和二级索引的具体结构如下 聚集索引的叶子节点下挂的是这一行的数据 。二级索引的叶子节点下挂的是该字段值对应的主键值。 当执行 select* from user where name ‘Arm’具体的查找过程如下 由于是根据name字段进行查询所以先根据name字段的二级索引中进行匹配查找。Lee—Geek—Arm在二级索引中只能查找到 Arm 对应的主键值 10。由于查询返回的数据是*(所有返回字段)所以还需要根据主键值10到聚集索引中查找10对应的记录15—10最终找到10对应的行row。最终拿到这一行的数据直接返回即可。 回表查询 先到二级索引中查找数据找到主键值再到聚集索引中根据主键值这种获取数据的方式就称之为回表查询。 思考以下两条SQL语句那个执行效率高? 为什么? A. select * from user where id 10 ; B. select * from user where name ‘Arm’ ; 备注: id为主键name字段创建的有索引 解答 A 语句的执行性能要高于B 语句。因为A语句直接走聚集索引直接返回数据。 而B语句需要先查询name字段的二级索引然后再查询聚集索引也就是需要进行回表查询。 思考InnoDB主键索引的Btree高度为多高呢 假设:一行数据大小为1k一页中可以存储16行这样的数据。InnoDB的指针占用6个字节的空间主键即使为bigint占用字节数为8。InnoDB存储引擎最小储存单元是页一页大小就是16k。B树叶子存的是数据内部节点存的是键值指针。索引组织表通过非叶子节点的二分查找法以及指针确定数据在哪个页中进而再去数据页中找到需要的数据 如果B树的高度为2的话即有一个根结点和若干个叶子结点。这棵B树的存放总记录数为根结点指针数*单个叶子节点记录行数 假设一行记录的数据大小为1k那么单个叶子节点可以存的记录数 16k/1k 16. 非叶子节点内存放多少指针呢假设主键ID为bigint类型长度为8字节(int类型的话一个int就是32位4字节)而指针大小是固定的在InnoDB源码中设置为6字节假设n指主键个数即key的个数n*8 (n 1) * 6 16K16*1024B , 算出n约为 1170,意味着根节点会有1170个key与1171个指针、因此一棵高度为2的B树能存放1171* 16 18736条这样的数据记录。同理一棵高度为3的B树能存放1171 * 1171 * 16 21939856也就是说可以存放两千万左右的记录。B树高度一般为1-3层已经满足千万级别的数据存储。索引语法 创建索引 CREATE [ UNIQUE | FULLTEXT ] INDEX index_name ON table_name (index_col_name,... ) ;查看索引 SHOW INDEX FROM table_name ;删除索引 DROP INDEX index_name ON table_name ;数据准备 create table tb_user(id int primary key auto_increment comment 主键,name varchar(50) not null comment 用户名,phone varchar(11) not null comment 手机号,email varchar(100) comment 邮箱,profession varchar(11) comment 专业,age tinyint unsigned comment 年龄,gender char(1) comment 性别 , 1: 男, 2: 女,status char(1) comment 状态,createtime datetime comment 创建时间 ) comment 系统用户表;INSERT INTO tb_user (name, phone, email, profession, age, gender, status,createtime) VALUES (吕布, 17799990000, lvbu666163.com, 软件工程, 23, 1,6, 2001-02-02 00:00:00); INSERT INTO tb_user (name, phone, email, profession, age, gender, status,createtime) VALUES (曹操, 17799990001, caocao666qq.com, 通讯工程, 33,1, 0, 2001-03-05 00:00:00); INSERT INTO tb_user (name, phone, email, profession, age, gender, status,createtime) VALUES (赵云, 17799990002, 17799990139.com, 英语, 34, 1,2, 2002-03-02 00:00:00); INSERT INTO tb_user (name, phone, email, profession, age, gender, status,createtime) VALUES (孙悟空, 17799990003, 17799990sina.com, 工程造价, 54,1, 0, 2001-07-02 00:00:00); ...... INSERT INTO tb_user (name, phone, email, profession, age, gender, status,createtime) VALUES (姜子牙, 17799990023, 37483844qq.com, 工程造价, 29,1, 4, 2003-05-26 00:00:00);name字段为姓名字段该字段的值可能会重复(不能创建唯一索引只能创建常规索引)为该字段创建索引。 CREATE INDEX idx_user_name ON tb_user(name);phone手机号字段的值是非空且唯一的为该字段创建唯一索引。 CREATE UNIQUE INDEX idx_user_phone ON tb_user(phone);为profession、age、status创建联合索引。 CREATE INDEX idx_user_pro_age_sta ON tb_user(profession,age,status);为email建立合适的索引来提升查询效率。 CREATE INDEX idx_email ON tb_user(email);查看tb_user表的所有的索引数据 show index from tb_user;SQL性能分析工具 SQL执行频率 MySQL 客户端连接成功后通过 show [session|global] status 命令可以提供服务器状态信息。通过如下指令可以查看当前数据库的INSERT、UPDATE、DELETE、SELECT的访问频次 -- session 是查看当前会话 ; -- global 是查询全局数据 ; SHOW GLOBAL STATUS LIKE Com_______;Com_delete: 删除次数Com_insert: 插入次数Com_select: 查询次数Com_update: 更新次数 可以在当前数据库再执行几次查询操作然后再次查看执行频次看看 Com_select 参数会不会变化。 慢查询日志 慢查询日志记录了所有执行时间超过指定参数long_query_time单位秒默认10秒的所有SQL语句的日志。 MySQL的慢查询日志默认没有开启可以查看一下系统变量 slow_query_log。 要开启慢查询日志需要在MySQL的配置文件/etc/my.cnf中配置如下信息 # 开启MySQL慢日志查询开关 slow_query_log1 # 设置慢日志的时间为2秒SQL语句执行时间超过2秒就会视为慢查询记录慢查询日志 long_query_time2配置完毕之后重新启动MySQL服务器进行测试查看慢日志文件中记录的信息/var/lib/mysql/localhost-slow.log。 systemctl restart mysqld再次查看开关情况慢查询日志已经打开了 测试执行如下SQL语句 select * from tb_user; -- 这条SQL执行效率比较高, 执行耗时 0.00sec select count(*) from tb_sku; -- 由于tb_sku表中, 预先存入了1000w的记录, count一次,耗时13.35sec在慢查询日志中只会记录执行时间超多我们预设时间2s的SQL执行较快的SQL是不会记录的。通过慢查询日志就可以定位出执行效率比较低的SQL从而有针对性的进行优化。 profile详情 show profiles 能够在做SQL优化时了解时间都耗费到哪里去了。 通过have_profiling参数查看当前MySQL是否支持profile操作。 SELECT have_profiling ;当前MySQL是支持 profile操作的默认开关0是关闭的。可以通过set语句在session/global级别开启profiling SET profiling 1;开关打开之后所执行的SQL语句都会被MySQL记录并记录执行时间消耗到哪儿去了执行如下的SQL语句 select * from tb_user; select * from tb_user where id 1; select * from tb_user where name 白起; select count(*) from tb_sku;执行一系列的业务SQL的操作然后通过如下指令查看指令的执行耗时 -- 查看每一条SQL的耗时基本情况 show profiles; -- 查看指定query_id的SQL语句各个阶段的耗时情况 show profile for query query_id; -- 查看指定query_id的SQL语句CPU的使用情况 show profile cpu for query query_id;explain EXPLAIN 或者 DESC命令获取 MySQL 如何执行 SELECT 语句的信息包括在 SELECT 语句执行过程中表如何连接和连接的顺序是否用到索引。 基本语法: -- 直接在select语句之前加上关键字 explain / desc EXPLAIN SELECT 字段列表 FROM 表名 WHERE 条件 ;Explain 执行计划中各个字段的含义: typeNULL(查询时不访问任何表) system(访问系统表) const(根据主键和唯一索引访问) eq_ref() ref(使用非唯一性的索引访问) range() index(扫描所有索引) all(全表扫描) 执行sql: explain select s.*,c.* from student s,course c, student_course sc where s.idsc.studentz-id and c.idsc.courseid;表执行顺序studentcoursestudent_course 索引使用 联合索引 最左前缀法则 如果索引了多列联合索引要遵守最左前缀法则。最左前缀法则指的是查询从索引的最左列开始并且不跳过索引中的列。如果跳跃某一列索引将会部分失效(后面的字段索引失效)。 查看tb_user 表所创建的索引 联合索引涉及到三个字段顺序分别为professionagestatus 最左前缀法则指的是查询时最左变的列即profession必须存在否则索引全部失效。而且中间不能跳过某一列否则该列后面的字段索引将失效。 explain select * from tb_user where profession 软件工程 and age 31 and status 0;# 索引长度54explain select * from tb_user where profession 软件工程 and age 31;# status索引长度5explain select * from tb_user where profession 软件工程; # age索引长度2explain select * from tb_user where age 31 and status 0; # 最左边列不存在索引全部失效与存放位置没有关系explain select * from tb_user where status 0; # 最左边列不存在索引全部失效与存放位置没有关系explain select * from tb_user where profession 软件工程 and status 0; # 索引跳过了某一列之后索引都失效范围查询 联合索引中出现范围查询(,)范围查询右侧的列索引失效。 explain select * from tb_user where profession 软件工程 and age 30 and status 0; # 索引长度49status索引失效规避使用, 索引失效情况 索引列运算不要在索引列上进行运算操作索引将失效 tb_user表中phone字段索引 当根据phone字段进行等值匹配查询时, 索引生效。 explain select * from tb_user where phone 17799990015; 当根据phone字段进行函数运算操作之后索引失效。 explain select * from tb_user where substring(phone,10,2) 15;字符串不加引号字符串类型字段使用时不加引号索引将失效。 如果字符串不加单引号对于查询结果没什么影响但是数据库存在隐式类型转换索引将失效。 explain select * from tb_user where profession 软件工程 and age 31 and status 0; explain select * from tb_user where profession 软件工程 and age 31 and status 0;模糊查询在like模糊查询中在关键字后面加%索引可以生效。而如果在关键字前面加了%索引将会失效。 explain select * from tb_user where profession like 软件%; explain select * from tb_user where profession like %工程; explain select * from tb_user where profession like %工%;or连接条件如果or条件一侧有索引一侧没有索引涉及到的索引都不会被用到。 由于age没有索引所以即使id、phone有索引索引也会失效。所以需要针对于age也要建立索引。 explain select * from tb_user where id 10 or age 23; explain select * from tb_user where phone 17799990017 or age 23;对age字段建立索引当or连接的条件左右两侧字段都有索引时索引才会生效。 create index idx_user_age on tb_user(age);数据分布影响如果MySQL评估使用索引比全表更慢则不使用索引。 select * from tb_user where phone 17799990000; select * from tb_user where phone 17799990020;MySQL在查询时会评估使用索引的效率与走全表扫描的效率如果走全表扫描更快则放弃索引走全表扫描。 因为索引是用来索引少量数据的如果通过索引查询返回大批量的数据则还不如走全表扫描来的快此时索引就会失效。 explain select * from tb_user where profession is null; explain select * from tb_user where profession is not null;将表中的profession设为null update tb_user set profession null;再次执行 一模一样的SQL语句先后执行了两次结果查询计划是不一样的为什么会出现这种现象这是和数据库的数据分布有关系。查询时MySQL会评估走索引快还是全表扫描快如果全表扫描更快则放弃索引走全表扫描。 因此is null 、is not null是否走索引得具体情况具体分析并不是固定的。 SQL提示 SQL提示是优化数据库的一个重要手段简单来说就是在SQL语句中加入一些人为的提示来达到优化操作的目的。 前提字段profession有一个单例索引idx_user_pro一个联合索引idx_user_pro_age_sta use index 建议MySQL使用哪一个索引完成此次查询仅仅是建议mysql内部还会再次进行评估。 explain select * from tb_user use index(idx_user_pro) where profession 软件工程;ignore index 忽略指定的索引 explain select * from tb_user ignore index(idx_user_pro) where profession 软件工程;force index 强制使用索引 explain select * from tb_user force index(idx_user_pro_age_sta) where profession 软件工程;覆盖索引 尽量使用覆盖索引减少select *。 覆盖索引是指查询使用了索引并且需要返回的列在该索引中已经全部能够找到 执行以下sql explain select id, profession from tb_user where profession 软件工程 and age 31 and status 0 ; explain select id, profession age,from tb_user where profession 软件工程 and age 31 and status 0 ; explain select id,profession,age, status from tb_user where profession 软件工程 and age 31 and status 0 ; explain select id,profession,age, status, name from tb_user where profession 软件工程 and age 31 and status 0 ; explain select * from tb_user where profession 软件工程 and age 31 and status 0;前几条SQL的结果为 Using where; Using Index ; 后两条SQL的结果为: Using index condition 。 在tb_user表中有一个联合索引 idx_user_pro_age_sta该索引关联了三个字段profession、age、status而这个索引也是一个二级索引所以叶子节点下面挂的是这一行的主键id。 所以当我们查询返回的数据在 id、profession、age、status 之中则直接走二级索引直接返回数据了。 如果超出这个范围就需要拿到主键id再去扫描聚集索引再获取额外的数据了这个过程就是回表。 而我们如果一直使用select* 查询返回所有字段值很容易就会造成回表查询除非是根据主键查询此时只会扫描聚集索引。 思考 一张表, 有四个字段(id, username, password, status), 由于数据量大, 需要对以下SQL语句进行优化, 该如何进行才是最优方案:select id,username,password from tb_user where username ‘itcast’; 答案: 针对于 username, password建立联合索引, sql为: create index idx_user_name_pass on tb_user(username,password);可以避免上述SQL语句在查询的过程中出现回表查询。 前缀索引 当字段类型为字符串varchartextlongtext等时有时候需要索引很长的字符串这会让索引变得很大查询时浪费大量的磁盘IO 影响查询效率。此时可以只将字符串的一部分前缀建立索引这样可以大大节约索引空间从而提高索引效率。 基本语法 create index idx_xxxx on table_name(column(n)) ;前缀长度 可以根据索引的选择性来决定选择性是指不重复的索引值基数和数据表的记录总数的比值索引选择性越高则查询效率越高 唯一索引的选择性是1是最好的索引选择性性能也是最好的。 select count(distinct email) / count(*) from tb_user ; select count(distinct substring(email,1,5)) / count(*) from tb_user ;示例为tb_user表的email字段建立长度为5的前缀索引。 create index idx_email_5 on tb_user(email(5));前缀索引的查询流程 具体过程如下: 由于是根据email字段进行查询所以先根据email字段的二级索引中进行匹配查找。daqia—lvbu6,在二级索引中只能查找到 lvbu6对应的主键值 1。由于查询返回的数据是*(所有返回字段)所以还需要根据主键值1到聚集索引中查找1对应的记录7—3—1最终找到1对应的行row。最终拿到这一行的数据对比email的值是不是传递的值是查询并返回之后再查询当前下一个节点的元素。 单列索引与联合索引 单列索引 即一个索引只包含单个列。 联合索引 即一个索引包含了多个列。 select id,name,phone from tb_user where phone 177999990010 and name 韩信;在and连接的两个字段 phone、name上都是有单列索引的但是最终mysql只会选择一个索引也就是说只能走一个字段的索引此时是会回表查询的。 创建phone和name字段的联合索引 create unique index idx_user_phone_name on tb_user(phone,name);在业务场景中如果存在多个查询条件考虑针对于查询字段建立索引时建议建立联合索引而非单列索引。 多条件联合查询时MySQL优化器会评估哪个字段的索引效率更高会选择该索引完成本次查询。 索引设计原则 针对于数据量较大且查询比较频繁的表建立索引。针对于常作为查询条件where、排序order by、分组group by操作的字段建立索引。尽量选择区分度高的列作为索引尽量建立唯一索引区分度越高使用索引的效率越高。(性别区分度不大)如果是字符串类型的字段字段的长度较长可以针对于字段的特点建立前缀索引。尽量使用联合索引减少单列索引查询时联合索引很多时候可以覆盖索引节省存储空间避免回表提高查询效率。要控制索引的数量索引并不是多多益善索引越多维护索引结构的代价也就越大会影响增删改的效率。 SQL优化 插入数据 需要一次性往数据库表中插入多条记录可以从以下三个方面进行优化 insert into tb_test values(1,tom); insert into tb_test values(2,cat); insert into tb_test values(3,jerry); .....优化方案一批量插入数据500-1000条 Insert into tb_test values(1,Tom),(2,Cat),(3,Jerry);优化方案二手动控制事务(默认一条insert语句自动提交数据) start transaction; insert into tb_test values(1,Tom),(2,Cat),(3,Jerry); insert into tb_test values(4,Tom),(5,Cat),(6,Jerry); insert into tb_test values(7,Tom),(8,Cat),(9,Jerry); commit;优化方案三主键顺序插入性能要高于乱序插入。 主键乱序插入 : 8 1 9 21 88 2 4 15 89 5 7 3 主键顺序插入 : 1 2 3 4 5 7 8 9 15 21 88 89大批量数据插入 如果一次性需要插入大批量数据(比如: 几百万的记录)使用insert语句插入性能较低可以使用MySQL数据库提供的load指令进行插入。操作如下 将数据脚本文件中的数据加载到表结构中 -- 客户端连接服务端时加上参数 -–local-infile需要加载本地文件 mysql –-local-infile -u root -p-- 设置全局参数local_infile为1开启从本地加载文件导入数据的开关 set global local_infile 1;-- 执行load指令将准备好的数据加载到表结构中每个数据用,分割每一行数据用/n分割 load data local infile /root/load_user_100w_sort.sql into table tb_user fields terminated by , lines terminated by \n ;在load时主键顺序插入性能高于乱序插入 主键优化 数据组织方式在InnoDB存储引擎中表数据都是根据主键顺序组织存放的这种存储方式的表称为索引组织表(index organized table IOT)。 行数据都是存储在聚集索引的叶子节点上的。在InnoDB引擎中数据行是记录在逻辑结构 page 页中的而每一个页的大小是固定的默认16K。也就意味着 一个页中所存储的行也是有限的如果插入的数据行row在该页存储不小将会存储到下一个页中页与页之间会通过指针连接。 页可以为空也可以填充一半也可以填充100%。每个页包含了2-N行数据(如果一行数据过大会行溢出)根据主键排列。 主键顺序插入效果 从磁盘中申请页 主键顺序插入 第一个页没有满继续往第一页插入当第一个也写满之后再写入第二个页页与页之间会通过指针连接当第二页写满了再往第三页写入。 主键乱序插入效果 加入1#,2#页都已经写满了存放了如图所示的数据此时再插入id为50的记录因为索引结构的叶子节点是有顺序的。按照顺序应该存储在47之后。 但是47所在的1#页已经写满了存储不了50对应的数据了。 那么此时会开辟一个新的页 3#。将1#页后一半的数据移动到3#页然后在3#页插入50。此时这三个页之间的数据顺序是有问题的 重新设置链表指针1#的下一个页是3# 3#的下一个页是2#。 上述的这种现象称之为 “页分裂”是比较耗费性能的操作。 删除记录 当删除一行记录时实际上记录并没有被物理删除只是记录被标记flaged为删除并且它的空间变得允许被其他记录声明使用。 当页中删除的记录达到 MERGE_THRESHOLD默认为页的50%InnoDB会开始寻找最靠近的页前 或后看看是否可以将两个页合并以优化空间使用。 删除数据并将页合并之后再次插入新的数据21则直接插入3#页 这个里面所发生的合并页的这个现象就称之为 “页合并”。 MERGE_THRESHOLD合并页的阈值可以自己设置在创建表或者创建索引时指定。 主键设计原则 满足业务需求的情况下尽量降低主键的长度。(二级索引占用空间大)插入数据时尽量选择顺序插入选择使用AUTO_INCREMENT自增主键尽量不要使用UUID做主键或者是其他自然主键如身份证号。业务操作时避免对主键的修改。 order by优化 MySQL的排序有两种方式 Using filesort : 通过表的索引或全表扫描读取满足条件的数据行然后在排序缓冲区sort buffer中完成排序操作所有不是通过索引直接返回排序结果的排序都叫 FileSort 排序。Using index : 通过有序索引顺序扫描直接返回有序数据这种情况即为 using index不需要额外排序操作效率高。 Using index的性能高而Using filesort的性能低在优化排序操作时尽量要优化为 Using index。 执行age,phone排序SQL explain select id,age,phone from tb_user order by age,phone; #都没有索引创建age,phone索引 create index idx_user_age_phone_aa on tb_user(age,phone);执行一下排序查询 单独对age升序排 explain select id,age,phone from tb_user order by age; # 使用了索引对age,phone 升序排 explain select id,age,phone from tb_user order by age, phone ; # 使用了索引根据age, phone进行升序排序就由原来的Using filesort 变为了 Using index性能就是比较高的了。 根据age, phone进行降序排序 explain select id,age,phone from tb_user order by age desc , phone desc ; # 使用了索引并反向扫描也出现了 Using index 但是Extra中出现了 Backward index scan这个代表反向扫描索引因为在MySQL中我们创建的索引默认索引的叶子节点是从小到大排序的而此时我们查询排序时是从大到小所以在扫描时就是反向扫描就会出现 Backward index scan。 在MySQL8版本中支持降序索引也可以创建降序索引。 对phone,age 升序排 explain select id,age,phone from tb_user order by phone , age; # 在索引之外需要额外进行外部的排序动作根据phoneage进行升序排序phone在前age在后违背了最左匹配法则索引失效 根据age升序排, phone降序排 explain select id,age,phone from tb_user order by age asc,phone desc; # 在索引之外需要额外进行外部的排序动作因为创建索引时如果未指定顺序默认都是按照升序排序的而查询时一个升序一个降序此时就会出现Using filesort。 创建联合索引(age 升序排序phone 倒序排序) create index idx_user_age_phone_ad on tb_user(age asc ,phone desc);再次执行如下SQL explain select id,age,phone from tb_user order by age asc , phone desc ; # 使用了索引如果根据age和phone创建了联合索引默认都是升序当age和phone升序排序age单字段升序age和phone降序排序都会走联合索引。其他情况会索引失效。一个升序一个降序的情况需要重新建立索引。 order by优化原则: 根据排序字段建立合适的索引多字段排序时也遵循最左前缀法则。尽量使用覆盖索引不用再回表查询避免索引排序失效。多字段排序, 一个升序一个降序此时需要注意联合索引在创建时的规则ASC/DESC。如果不可避免的出现filesort大数据量排序时可以适当增大排序缓冲区大小sort_buffer_size(默认256k)超过磁盘缓冲区大小会在磁盘排序性能低。 group by优化 将 tb_user 表的索引全部删除掉在没有索引的情况下执行如下SQL查询执行计划 explain select profession , count(*) from tb_user group by profession ;#用到了缓冲区效率较低针对于 profession age status 创建一个联合索引 create index idx_user_pro_age_sta on tb_user(profession , age , status);再执行前面相同的SQL查看执行计划 explain select profession , count(*) from tb_user group by profession ; # 使用了索引根据age分组 explain select profession , count(*) from tb_user group by age ; #不满足最左前缀法则根据professionage分组 explain select profession , age,count(*) from tb_user group by profession,age ; # 使用了索引条件中有profession满足最左前缀法则 explain select age,count(*) from tb_user where profession 软件工程group by profession,age ;通过以下两点进行优化以提升性能 在分组操作时可以通过索引来提高效率。分组操作时索引的使用也是满足最左前缀法则的。 limit优化 在数据量比较大时如果进行limit分页查询在查询时越往后分页查询效率越低。 当在进行分页查询时如果执行 limit 2000000,10 此时需要MySQL排序前2000010 记录仅仅返回 2000000 - 2000010 的记录其他记录丢弃查询排序的代价非常大 。 一般分页查询时通过创建 覆盖索引 能够比较好地提高性能可以通过覆盖索引加子查询形式进行优化。 explain select * from tb_sku t , (select id from tb_sku order by id limit 2000000,10) a where t.id a.id;count优化 select count(*) from tb_user ;MyISAM 引擎把一个表的总行数存在了磁盘上因此执行 count(*) 的时候会直接返回这个数效率很高 但是如果是带条件的countMyISAM也慢。InnoDB 引擎执行 count(*) 的时候需要把数据一行一行地从引擎里面读出来然后累积计数。 如果要大幅度提升InnoDB表的count效率主要的优化思路自己计数(可以借助于redis这样的数据库进行,但是如果是带条件的count又比较麻烦)。 count的用法 count() 是一个聚合函数对于返回的结果集一行行地判断如果 count 函数的参数不是NULL累计值就加 1否则不加最后返回累计值。 count主键InnoDB引擎会遍历整张表把每一行的主键id值都取出来返回给服务层。服务层拿到主键后直接按行进行累加(主键不可能为null)。count字段 没有not null约束InnoDB引擎会遍历整张表把每一行的字段值都取出来返回给服务层判断是否为null不为null计数累加。有not null约束InnoDB引擎会遍历整张表把每一行的字段值都取出来返回给服务层直接按行进行累加。 count数字InnoDB引擎遍历整张表但不取值服务层对于返回的每一行放一个数字“1”进去直接按行进行累加count*InnoDB引擎并不会把全部字段取出来而是专门做了优化不取值服务层直接按行进行累加。 按照效率排序的话count(字段) count(主键 id) count(1) ≈ count(*) update优化 update course set name javaEE where id 1 ;在执行更新的SQL语句时会锁定id为1这一行的数据然后事务提交之后行锁释放 update course set name SpringBoot where name PHP ; 当开启多个事务在执行上述的SQL时会发现行锁升级为了表锁。 导致该update语句的性能大大降低。 InnoDB的行锁是针对索引加的锁不是针对记录加的锁 更新的条件必须有索引并且该索引不能失效否则会从行锁升级为表锁 。
http://www.dnsts.com.cn/news/148971.html

相关文章:

  • 广西城市建设学校官方网站手机网站模板网
  • 云南网站建设价格php和网站建设
  • 襄阳网站seo技巧一个小程序一年的费用是多少
  • 网站页面html静态化是什么意思建设网站涉及的技术
  • wordpress後台建站登封seo公司
  • 站长统计导航窗口商城网站系统建设
  • 杭州有做网站深圳公众号小程序开发公司
  • 专业网站建设微信商城开发专业建设费用怎么花
  • 乌兰浩特网站建设wordpress抓取文章插件
  • 做网页用的网站wordpress 内页模板
  • 技术支持 网站建设国产做爰全免费的视频网站
  • 淘宝网站开发多少金额高级网站开发工程师 证书
  • php网站开发外包建设银行人力资源系统网站怎么进
  • 网站404页面设置郑州建设信息网打不开
  • 红色网站 推荐重庆娱乐场所最新通知
  • 网站开发菜鸟适合用什么软件郑州网站模板哪里有
  • 医院网站前置审批最快多久出来广州设计网站培训学校
  • 苍溪规划和建设局网站微信网站开发制作公司
  • 网站设计公司 长沙怎么做国外游戏下载网站
  • 做aa视频网站人社局网站建设步骤
  • 网站建设能否建立国外站网站建设的用户环境
  • 企业网站推广的名词解释青岛网站建设公司在哪
  • 溧阳手机网站哪里做东莞最大的网络公司
  • 苏宁易购网站建设情况南京需要做网站的公司
  • 网站的惩罚期要怎么做付费论坛源码
  • 网站建设捌金手指下拉八传媒公司网站建设思路
  • 如何制作微网站织梦怎么做中英文双语网站
  • 网站后台的东西都是要上传到在虚拟主机上面吗中国推广网站
  • 做二手家电网站怎样阿里云域名续费
  • 江门站官网江西省公共资源交易网