MySQL3

MySQL数据库3

1. 存储过程

  • 建立存储过程css

    1. 语法格式
             
             
             
             
             
      • 1
      • 2
      • 3
      CREATE PROCEDURE <==建立存储过程命令 sp_name([ proc_parameter[,proc_parameter...]]) <==命名存储过程及参数 routime_body
    2. 说明
      1. routime_body
        符合规定的SQL过程语句,可使用复合语法(例如BEGIN…END),复合语句能够包含声明,循环和其余控制结构语句
      2. proc_parameter
        参数内容分为[IN|OUT|INOUT] parameter_name type
        其中IN表示输入参数,OUT表示输出参数,INOUT表示既能够输入也能够输出;param_name表示参数名称;type表示参数的类型
  • 查看存储过程列表
    SHOW PROCEDURE STATUS
    此内容在mysql自建数据库information_schema.ROUTINES表中html

  • 查看存储过程定义
    SHOW CREATE PROCEDURE sp_namemysql

  • 调用存储过程:web

    1. 有参数调用
      CALL sp_name([ proc_parameter[,proc_parameter…]])
    2. 无参数调用
      CALL sp_name
      说明:当无参时,能够省略"()",当有参数时,不可省略"()”
    3. 跨数据库调用
      存储过程定义是依赖于数据库的,在哪一个数据库建立,就在哪一个数据库使用,在其余数据库使用时,要加上数据库名称
             
             
             
             
             
      • 1
      MariaDB [db2]> CALL hellodb.showtime;
  • 存储过程修改
    ALTER语句修改存储过程只能修改存储过程的注释等可有可无的东西,不能修改存储过程体,因此要修改存储过程,方法就是删除重建算法

  • 删除存储过程:
    DROP PROCEDURE [IF EXISTS] sp_namesql

  • 示例shell

    1. 建立无参存储过程:
             
             
             
             
             
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      MariaDB [hellodb]> delimiter // <==修改定界符为// MariaDB [hellodb]> CREATE PROCEDURE <==建立存储过程命令 -> showTime() <==定义函数名称及参数 -> BEGIN <==routime_body复合语法 -> SELECT now(); <==SQL过程语句 -> END// MariaDB [hellodb]> delimiter ; MariaDB [hellodb]> CALL showTime; <==调用存储过程
    2. 建立含参存储过程:只有一个IN参数
             
             
             
             
             
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      MariaDB [hellodb]> delimiter // MariaDB [hellodb]> CREATE PROCEDURE -> selectById(IN uid SMALLINT UNSIGNED) <==定义存储过程名,为输入参数名为uid 类型 -> BEGIN -> SELECT * FROM students WHERE stuid= uid; -> END// MariaDB [hellodb]> delimiter ; MariaDB [hellodb]> call selectById(2);
    3. 在存储过程当中定义局部变量
             
             
             
             
             
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      MariaDB [hellodb]> delimiter // MariaDB [hellodb]> CREATE PROCEDURE dorepeat(n INT) -> BEGIN -> SET @i= 0; <==定义变量@i -> SET @sum = 0; <==定义变量@i -> REPEAT SET @sum = @sum+@i; SET @i= @i+ 1; <==REPEAT为重复的意思,相似循环,与结尾的REPEAT成对 -> UNTIL @i> n END REPEAT; <==UNTIL定义结束时间 -> END// MariaDB [hellodb]> delimiter ; MariaDB [hellodb]> CALL dorepeat(100); MariaDB [hellodb]> SELECT @sum; <==查看返回值@sum
    4. 建立含参存储过程:包含IN参数和OUT参数,OUT能够将参数传到mysql中使用
             
             
             
             
             
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      MariaDB [hellodb]> delimiter // MariaDB [hellodb]> CREATE PROCEDURE -> deleteById(IN uid SMALLINT UNSIGNED, OUT num SMALLINT UNSIGNED) -> BEGIN -> DELETE FROM students WHERE stuid= uid; -> SELECT row_count() into num; <==row_count()为系统函数,记录删除行次数 -> END// MariaDB [hellodb]> delimiter ; MariaDB [hellodb]> call deleteById(2,@Line); MariaDB [hellodb]> SELECT @Line;
      说明:建立存储过程deleteById,包含一个IN参数和一个OUT参数.调用时,传入删除的ID和保存被修改的行数值的用户变量@Line,select@Line;输出被影响行数
  • 存储过程优点:数据库

    1. 存储过程把常用的SQL语句或业务逻辑封装起来,预编译保存在数据库中,当须要时从数据库中直接调用,省去了编译的过程
    2. 提升了运行速度
    3. 同时下降网络数据传输量
  • 存储过程与自定义函数的区别:vim

    1. 存储过程实现的过程要复杂一些,而函数的针对性较强
    2. 存储过程能够有多个返回值,而自定义函数只有一个返回值
    3. 存储过程通常独立的来执行,而函数每每是做为其余SQL语句的一部分来使用
  • 流程控制
    存储过程和函数中可使用流程控制来控制语句的执行api

    1. IF:用来进行条件判断。根据是否知足条件,执行不一样语句
    2. CASE:用来进行条件判断,可实现比IF语句更复杂的条件判断
    3. LOOP:重复执行特定的语句,实现一个简单的循环
    4. LEAVE:用于跳出循环控制
    5. ITERATE:跳出本次循环,而后直接进入下一次循环
    6. REPEAT:有条件控制的循环语句。当知足特定条件时,就会跳出循环语句
    7. WHILE:有条件控制的循环语句

2. 触发器(trigger)

  • 概念
    触发器的执行不是由程序调用,也不是由手工启动,而是由事件(对表的增、删、改)来触发、激活从而实现执行

  • 建立触发器

    1. 语法格式
             
             
             
             
             
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      CREATE [DEFINER = { user | CURRENT_USER }] TRIGGER trigger_name trigger_time <==触发器的时间 trigger_event <==触发器的事件 ON tbl_name <==在那张表上 FOR EACH ROW <==针对那一行 trigger_body <==触发动做
    2. 说明
      1. trigger_name:触发器的名称
      2. trigger_time:{ BEFORE | AFTER },表示在事件以前或以后触发
      3. trigger_event::{ INSERT |UPDATE | DELETE },触发的具体事件
      4. tbl_name:该触发器做用在表名
  • 查看触发器

    1. 在触发器建立数据库内输入
      SHOW TRIGGERS
    2. 查询系统自建表information_schema.triggers的方式指定查询条件,查看指定的触发器信息。
             
             
             
             
             
      • 1
      • 2
      • 3
      MariaDB [db2]> use information_schema; Database changed MariaDB [information_schema]> SELECT * FROM triggers WHERE trigger_name='trigger_student_count_insert'\G
  • 删除触发器
    DROP TRIGGER trigger_name;

  • 示例

    1. 建立两个表student_info和student_count,给student_count设置一个初始值0
             
             
             
             
             
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      '1. 建立表student_info,存放id和姓名,主键为id' MariaDB [db2]> CREATE TABLE student_info( -> stu_id INT(11) NOT NULL AUTO_INCREMENT, -> stu_name VARCHAR(255) DEFAULT NULL, -> PRIMARY KEY (stu_id) -> ); '2. 建立表 student_count,汇总学生数' MariaDB [db2]> CREATE TABLE student_count( -> student_count INT(11) DEFAULT 0 -> ); 3. '为表 student_count,写入一个初始值0' MariaDB [db2]> INSERT INTO student_count VALUES(0);
    2. 建立触发器,在向学生表INSERT数据时,学生数增长,DELETE学生时,学生数减小
             
             
             
             
             
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      1. 增长学员触发器 MariaDB [db2]> CREATE TRIGGER <==建立命令 -> trigger_student_count_insert <==触发器名称 -> AFTER INSERT <==触发时间 -> ON student_info FOR EACH ROW <==做用在表student_info的每一行 -> UPDATE student_count SET student_count=student_count+1; <==触发条件 MariaDB [db2]> CREATE TRIGGER trigger_student_count_delete -> AFTER DELETE -> ON student_info FOR EACH ROW -> UPDATE student_count SET student_count=student_count-1;
    3. 增长、删除学员记录,验证触发器效果
             
             
             
             
             
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      '1. 增长两条学员信息' MariaDB [db2]> insert student_info values(1,'wang'); Query OK, 1 row affected (0.00 sec) MariaDB [db2]> insert student_info values(2,'mage'); Query OK, 1 row affected (0.01 sec) '2. 查看学员统计表是否自动增长' MariaDB [db2]> select * from student_count; +---------------+ | student_count | +---------------+ | 2 | +---------------+ '3. 删除学员信息,达成触发条件' MariaDB [db2]> delete from student_info; Query OK, 2 rows affected (0.00 sec) '4. 查看触发器效果' MariaDB [db2]> select * from student_count; +---------------+ | student_count | +---------------+ | 0 | +---------------+

3. MySQL用户和权限管理

3.1 MyAQL用户

  • 受权表存放位置
    元数据数据库mysql中系统受权表
    db, host, user
    columns_priv, tables_priv, procs_priv, proxies_priv

  • 建立用户:

    1. 命令:CREATE USER
    2. 默认权限:USAGE
    3. 语法格式:
      CREATE USER 'USERNAME'@'HOST' [IDENTIFIED BY 'password'];
    4. 示例
      建立用户v9,容许此用户在192.168.50.网段的主机登陆本机的数据库,密码为123456
             
             
             
             
             
      • 1
      • 2
      • 3
      MariaDB [db2]> CREATE USER <==建立用户命令 'v9'@'192.168.50.%' <==定义用户名,容许登陆主机IP IDENTIFIED BY '123456'; <==建立密码,IDENTIFIED BY为定义密码参数
  • 用户重命名:

    1. 命令
      RENAME USER
    2. 语法格式
      RENAME USER old_user_name TO new_user_name
  • 删除用户:

    1. 方法1,用户控制命令(在线链接的用户若是没有任何操做也能够删除)
      1. 命令
        DROP USER
      2. 语法格式
        DROP USER ‘USERNAME’@'HOST‘
      3. 示例:删除安装系统时的匿名用户
                 
                 
                 
                 
                 
        • 1
        MariaDB [db2]> DROP USER ''@'localhost'
    2. 方法2,对表进行操做,删除对应行,不会当即生效,须要从新载入‘ FLUSH PRIVILEGES’
             
             
             
             
             
      • 1
      • 2
      MariaDB [db2]> DELETE FROM mysql.user WHERE user='v9' AND host='192.168.50.100'; MariaDB [db2]> FLUSH PRIVILEGES <==若是未生效,须要重复文件
  • 修改密码:

    1. 方法一:用户控制命令

      1. 语法格式
        SET PASSWORD FOR ‘user’@‘host’ = PASSWORD(‘password’);
      2. 示例
                 
                 
                 
                 
                 
        • 1
        MariaDB [(none)]> SET PASSWORD FOR 'v9'@'192.168.50.100'=password('123456')
    2. 方法二:表操做命令

      1. 语法格式
        UPDATE mysql.user SET password=PASSWORD(‘password’) WHERE clause;
      2. 示例
                 
                 
                 
                 
                 
        • 1
        MariaDB [(none)]> UPDATE mysql.user SET password=password('123') WHERE host='hai7-8';
        此方法若是没有当即生效,须要执行下面指令:
                 
                 
                 
                 
                 
        • 1
        mysql> FLUSH PRIVILEGES;
    3. 方法三:登陆mysql时,命令行命令

      1. 语法格式
        mysqladmin -u root -poldpassword password ‘newpass‘
      2. 示例
                 
                 
                 
                 
                 
        • 1
        • 2
        • 3
        -p后为旧密码,这里旧密码为空,password后为新密码 [root@hai7-8 yum.repos.d]$mysqladmin -uroot -p'' password '123456' Enter password: <==输入旧密码
  • 忘记管理员密码的解决办法:

    1. 修改配置文件,子[mysqld]块组下,加入skip-grant-tables,从新启动服务
      –skip-grant-tables <==忽略受权表,也就是登陆不检查密码
      –skip-networking <==忽略网络功能,即断开网络,避免其余用户远程登陆
    2. 重启服务后,进入mysql后,使用UPDATE命令修改管理员密码
             
             
             
             
             
      • 1
      • 2
      MariaDB [(none)]> update mysql.user set password=''; <==实验环境,这里就设为空密码了 MariaDB [(none)]> FLUSH PRIVILEGES; <==将修改生效
    3. 关闭mysqld进程,移除配置文件中skip-grant-tables项,重启服务

3.2 MyAQL权限管理

  • 权限类别

    1. 管理类
权限 描述
CREATE TEMPORARY TABLES 建立临时表权限
CREATE USER 建立用户权限
FILE 文件访问权限
SUPER 执行kell线程权限
SHOW DATABASES 查看数据库权限
RELOAD 执行flush-hosts, flush-logs, flush-privileges, flush-status, flush-tables, flush-threads, refresh, reload等命令的权限
SHUTDOWN 关闭数据库权限
REPLICATION SLAVE 复制权限
REPLICATION CLIENT 复制权限
LOCK TABLES 锁表权限
PROCESS 查看进程权限
  1. 程序类:FUNCTION、PROCEDURE、TRIGGER
权限 描述
CREATE 建立数据库、表或索引权限
ALTER 更改表权限
DROP 删除数据库或表权限
EXCUTE 执行存储过程权限
  1. 数据库和表级别:DATABASE、TABLE
权限 描述
ALTER 更改表权限
CREATE 建立数据库、表或索引权限
CREATE VIEW 建立视图权限
DROP 删除数据库或表权限
INDEX 索引权限
SHOW VIEW 查看视图权限
GRANT OPTION 能将本身得到的权限转赠给其余用户
  1. 数据操做:
权限 描述
SELECT 查询权限
INSERT 插入权限
DELETE 删除数据权限
UPDATE 更新权限
  1. 字段级别:
权限 描述
SELECT(col1,col2,…) 指定字段查询权限
UPDATE(col1,col2,…) 指定字段更新权限
INSERT(col1,col2,…) 指定字段插入权限
  1. 全部权限:ALL PRIVILEGES 或ALL

3.3 受权操做

参考:https://dev.mysql.com/doc/refman/5.7/en/grant.html

  • 受权指令 GRANT
    1. 语法格式
      GRANT priv_type[(column_list)],… ON [object_type] priv_levelTO ‘user’@‘host’ [IDENTIFIED BY ‘password’] [WITH GRANT OPTION];

    2. 说明

      1. priv_type
        权限类别: 例如ALL [PRIVILEGES]
      2. (column_list)
        针对于哪一列进行受权
      3. ON:表示将在哪一个对象上实施受权
      4. object_type
        实施对象,要指明库名(TABLE| FUNCTION | PROCEDURE)
      5. priv_level
        权限级别: *(全部库) | *.* | db_name.* | db_name.tbl_name| tbl_name(当前库的表) | db_name.routine_name(指定库的函数,存储过程,触发器)
      6. [IDENTIFIED BY ‘password’]
        设置密码,建立用户受权一块儿操做时使用
      7. with_option(受权的特殊选项)
        1. GRANT OPTION:运行将权限受权给他人
        2. MAX_QUERIES_PER_HOUR count:限定在每小时能够查询的次数
        3. MAX_UPDATES_PER_HOUR count:最多更新多少次
        4. MAX_CONNECTIONS_PER_HOUR count:最多链接次数
        5. MAX_USER_CONNECTIONS count:受权用户的最大链接数
    3. 示例
      受权用户v9@'192.168.50.100’能够对 hellodb数据库中students表查询id和name的权限

           
           
           
           
           
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      MariaDB [hellodb]> grant select(stuid,name) on hellodb.students to v9@'192.168.50.100' '在192.168.50.100主机上使用帐号v9查看授予的权限' MariaDB [hellodb]> desc students; +-------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+------------------+------+-----+---------+----------------+ | StuID | int(10) unsigned | NO | PRI | NULL | auto_increment | | Name | varchar(50) | NO | | NULL | | +-------+------------------+------+-----+---------+----------------+

      受权而且建立帐号

           
           
           
           
           
      • 1
      MariaDB [(none)]> grant all on *.* to v9@'192.168.50.109' IDENTIFIED BY '123456';
  • 回收权限指令 REVOKE
    1. 语法格式
           
           
           
           
           
      • 1
      • 2
      • 3
      • 4
      REVOKE priv_type[(column_list)] [ , priv_type[(column_list)]] ... ON [object_type] priv_level FROM user [, user] ...
    2. 示例
      回收用户 v9@'192.168.50.100’在数据库hellodb中students表上的查看字段stuid,name的权限
           
           
           
           
           
      • 1
      • 2
      • 3
      MariaDB [(none)]> REVOKE SELECT (stuid,name) -> ON `hellodb`.`students` -> FROM v9@'192.168.50.100';
  • 查看指定用户得到的受权:
    1. 使用帮助
      Help SHOW GRANTS
    2. 查询指定用户权限
      1. 语法格式
        SHOW GRANTS FOR ‘user’@‘host’;
      2. 示例
               
               
               
               
               
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        MariaDB [hellodb]>SHOW GRANTS FOR v9@'192.168.50.100'; +----------------------------------------------------------------------------------------------------------------+ | GRANT USAGE ON *.* TO 'v9'@'192.168.50.100' IDENTIFIED BY PASSWORD '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9' | 链接权限 | GRANT SELECT (name, stuid) ON `hellodb`.`students` TO 'v9'@'192.168.50.100' 查询权限 | +----------------------------------------------------------------------------------------------------------
    3. 查看当前用户的权限
      SHOW GRANTS FOR CURRENT_USER[()];
    4. 注意项
      MariaDB服务进程启动时会读取mysql库中全部受权表至内存
      1. GRANT或REVOKE等执行权限操做会保存于系统表中,MariaDB的服务进程一般会自动重读受权表,使之生效
      2. 对于不可以或不能及时重读受权表的命令,可手动让MariaDB的服务进程重读受权表:mysql> FLUSH PRIVILEGES;
      3. 回收受权,或者受权其余权限后,用户须要从新登陆才能够生效

4. 存储引擎

4.1 从功能模块看MySQL体系结构

在这里插入图片描述

  • 各模块说明
    1. 初始化模块
      MySQL启动的时候,对整个系统作各类各样的初始化操做,好比各类buffer,cache结构的初始化和内存空间的申请,各类系统变量、存储引擎的初始化设置等

    2. 链接管理模块
      负责管理远程链接用户请求,接收链接请求,转发全部链接请求到线程管理模块

    3. 线程管理模块
      管理MYsQl的多个线程,负责为链接用户分配一个线程单独服务以及回收退出用户的空闲线程,回收的线程能够重复使用

    4. 用户模块
      用户帐号管理,主要包括用户的登陆链接权限控制和用户的受权管理

    5. 命令分发器:
      在MySQL中咱们习惯将全部的Client端发送给Server端的命令都称为query,服务线程收到客户端的query后,传递给专门负责将各类query进行分类而后转发给各个对应的处理模块,这个模块就是命令分发器,主要工做就是讲query语句进行语义和语法的分析,而后按不一样的操做类型进行分类,而后作针对性的转发

    6. 查询缓存模块
      将客户端提交的SELECT类query请求的返回结果cache到内存中,与此quer的一个hash值作对应,此query所去数据的基表发生任何数据变化后,MySQL会自动使此query的cache失效,查询缓存模块对性能的提升很是显著,相对的对内存的消耗也很是大

    7. 日志记录模块
      负责真个系统级别的逻辑层的日志记录,包括error log, binary log,slow query log等

    8. 命令解析器
      非查询命令经过命令发生器,发送到命令解析器上,再分发到对应的模块中进行管理

    9. 查询优化器:
      根据客户端请求的query语句,和数据库中的一些统计信息,在一系列算法的基础上进行分析,得出最有策略,告诉后面的程序如何取得query语句的结果

    10. 表变动模块
      负责完成一些DML和DDL的query,如:updatedelteinsertcreate tablealter table等语句的处理

    11. 表维护模块
      表的状态监测,错误修复,以及优化和分析等工做

    12. 复制模块
      分为Master模块和Slave模块两部分,Master模块主要负责在replication环境中读取Master端的binary日志,以及与slave端的I/O线程交互等工做。Slave模块负责从Master端请求和接收binary日志,并写入本地relay log中的I/O线程,还要负责从relay log中读取相关日志文件,而后解析成能够在Slave端正确执行并获得和Master端彻底相同的结果的命令并交给slave执行的SQL线程

    13. 状态模块
      负责在客户端请求系统状态的时候,将各类张贴数据返回给用户,像DBA经常使用的各类show status命令,show variables命令等,所获得的结果都是这个模块返回的

    14. 访问控制模块:
      根据用户模块中各用户的受权信息,以及数据库自身特有的各类约束,来控制用户对数据的访问

    15. 表管理模块
      维护表的定义文件(也就是*.frm文件)、表结构信息cache、table级别的锁管理

    16. 存储引擎接口模块:
      决定了将用户数据如何保存到物理设备上

    17. 网络交互模块
      底层网络交互模块,抽象出底层网络交互所使用的接口api,实现底层网络数据的接收与发送,以方便其余各个模块调用,以及对这一部分的维护,全部源代码都在vio文件夹下面

    18. 核心API
      提供须要很是高效的底层操做功能优化实现,包括各类底层数据结构的实现,特殊算法的实现,字符串处理,数字处理等,小文件I/O,格式化输出,以及内存管理;API模块的全部源代码集中在mysys和strings文件夹下

4.2 存储引擎

在这里插入图片描述

  • 数据库特征说明
    1. srorage limits
      最大存储
    2. Transactions:
      事务,多个操做做为一个总体出现
    3. Locking granularity
      锁,避免同时操做,带来不可预期的结果
    4. MVCC:
      1. 做用
        多版本并发控制机制,在一个数据库中可能有多个事务同时访问一个资源,若是没有控制机制,极可能出现脏数据,MVCC控制机制能够解决此问题
      2. 原理
        在数据库中的表,系统会增长两个隐藏字段insert 和delete,分别记录行数据建立和删除时的版本号,此版本号是随事务的建立而不断增加的数字,在事务开始时会记录它本身的系统版本号,后来的事务只会比以前的事务编号大
        事务对表作出insert操做时,会在insert字段增长作此操做事务的编号,delete会在删除字段增长编号,修改会同时在insert和delete字段增长编号。
      3. 事务DELECT表时,获得的数据
        1. 必须找到一个行的版本,它至少要和事务的版本同样老(也即它的版本号不大于事务的版本号)。这保证了无论是事务开始以前,或者事务建立时,或者修改了这行数据的时候,这行数据是存在的。
        2. 这行数据的删除版本必须是未定义的或者比事务版本要大。这能够保证在事务开始以前这行数据没有被删除。这里的不是真正的删除数据,而是标志出来的删除。真正意义的删除是在commit的时候。
    5. Geospatial data type support
      地理空间数据类型支持
    6. Geospatial indexing support
      地理空间索引支持
    7. B-tree indexes:B-tree索引
      全部的索引节点都按照balance tree的数据结构来存储,全部的索引数据节点都在叶节点
    8. T-tree indexes:T-tree 索引
    9. Hash indexes:哈希索引
    10. Full-text search indexes:全文索引
    11. Clustered indexes:汇集索引
    12. Data caches:数据缓存,将表内的数据放在内存中,让用户直接使用
    13. index caches:索引缓存
    14. Compressed data:压缩数据
    15. Encrypted data:加密数据
    16. Cluster database support:集群数据库支持
    17. Replication support:复制支持
    18. Foreign key support :外键支持
    19. Backup/point-in-time recovery:备份实时恢复
    20. Query cache support:查询缓存支持

4.3 MyISAM引擎

  • 特色

    1. 不支持事务,操做只能一步一步执行,若是在执行过程当中出现故障,很难保证数据的完整性和一致性
    2. 表级锁定,影响并发操做
    3. 读写相互阻塞,写入不能读,读时不能写
    4. 只缓存索引
    5. 不支持外键约束
    6. 不支持聚簇索引
    7. 读取数据较快,占用资源较少
    8. 不支持MVCC(多版本并发控制机制)高并发
    9. 崩溃恢复性较差
    10. MySQL5.5.5前默认的数据库引擎
  • 适用场景
    只读(或者写较少)、表较小(能够接受长时间进行修复操做)

  • 支持索引类型

    1. B-TREE索引
      是参与一个索引的全部字段的长度之和不能超过1000 字节
    2. R-TREE索引
      主要设计用于为存储空间和多
      维数据的字段作索引,因此目前的MySQL 版原本说,也仅支持geometry 类型的字段做索引。
    3. Full-text 索引
      Full-text 索引就是咱们长说的全文索引,他的存储结构也是b-tree。主要是为了
      解决在咱们须要用like 查询的低效问题
  • MyISAM数据库文件存放
    对于每个表对应有三个文件,存放在所属数据库的文件夹下

    1. tbl_name.frm:
      与表相关的元数据信息,包括表结构的定义信息
    2. tbl_name.MYD:
      存放表数据的文件
    3. tbl_name.MYI:
      存放索引相关信息文件

4.4 InnoDB引擎

  • 特色:
    1. 锁定集中的改进,行级锁,经过索引来完成
    2. 支持事务,适合处理大量短时间事务,innodb引擎最重要的一点
    3. 读写阻塞与事务隔离级别相关
    4. 可缓存数据和索引
    5. 实现外键约束
      Innodb 实现了外键引用这一数据库的重要特性,使在数据库端控制部分数据的完整性成为可能。
    6. 支持聚簇索引
    7. 崩溃恢复性更好
    8. 支持MVCC高并发
    9. 从MySQL5.5后支持全文索引
    10. 从MySQL5.5.5开始为默认的数据库引擎
  • InnoDB数据库文件
    1. 两类文件放在数据库独立目录中
      1. 数据文件(存储数据和索引):tb_name.ibd
      2. 表格式定义:tb_name.frm
    2. 全部InnoDB表的数据和索引放置于同一个表空间中
      表空间文件:datadir定义的目录下
      数据文件:ibddata1, ibddata2, …
    3. 设置每一个表单独使用一个表空间存储表的数据和索引
      启用:innodb_file_per_table=ON(MariaDB5.5之后版本默认开启)
      参看:https://mariadb.com/kb/en/library/xtradbinnodb-server-system-variables/#innodb_file_per_table
  • MySQL中的系统数据库使用的引擎
    1. mysql数据库
      是mysql的核心数据库,相似于sql server中的master库,主要负责存储数据库的用户、权限设置、关键字等mysql本身须要使用的控制和管理信息
           
           
           
           
           
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      '查看mysql数据库中文件的结构' MariaDB [(none)]> show table status from mysql\G *************************** 30. row *************************** Name: user Engine: MyISAM <==存储引擎为 MyISAM Version: 10 Row_format: Dynamic ......省略 Comment: Users and global privileges
    2. PERFORMANCE_SCHEMA数据库
      MySQL 5.5开始新增的数据库,主要用于收集数据库服务器性能参数(例如链接状况、负载状况),库里表的存储引擎均为PERFORMANCE_SCHEMA,用户不能建立存储引擎为PERFORMANCE_SCHEMA的表
           
           
           
           
           
      • 1
      • 2
      • 3
      • 4
      MariaDB [(none)]> show table status from performance_schema\G *************************** 52. row *************************** Name: users Engine: PERFORMANCE_SCHEMA
    3. information_schema数据库
      MySQL 5.0以后产生的,一个虚拟数据库,物理上并不存在。information_schema数据库相似与“数据字典”,提供了访问数据库元数据的方式,即数据的数据。好比数据库名或表名,列类型,访问权限(更加细化的访问方式),使用的存储引擎为MEMORY
           
           
           
           
           
      • 1
      • 2
      • 3
      • 4
      MariaDB [(none)]> show table status from information_schema\G *************************** 75. row *************************** Name: INNODB_SYS_SEMAPHORE_WAITS Engine: MEMORY

4.5 其它存储引擎

  • Performance_Schema
    mysql自建数据库 performance_schema使用的引擎
  • Memory
    将全部数据存储在RAM中,以便在须要快速查找参考和其余相似数据的环境中进行快速访问。适用存放临时数据,之前被称为HEAP引擎
  • MRG_MyISAM
    使MySQL DBA或开发人员可以对一系列相同的MyISAM表进行逻辑分组,并将它们做为一个对象引用。适用于VLDB(Very Large Data Base)环境,如数据仓库
  • Archive
    为存储和检索大量不多参考的存档或安全审核信息,只支持SELECT和INSERT操做;支持行级锁和专用缓存区
  • Federated联合
    用于访问其它远程MySQL服务器一个代理,它经过建立一个到远程MySQL服务器的客户端链接,并将查询传输到远程服务器执行,然后完成数据存取,提供连接单独MySQL服务器的能力,以便从多个物理服务器建立一个逻辑数据库。很是适合分布式或数据集市环境
  • BDB
    可替代InnoDB的事务引擎,支持COMMIT、ROLLBACK和其余事务特性
  • Cluster/NDB
    MySQL的簇式数据库引擎,尤为适合于具备高性能查找要求的应用程序,这类查找需求还要求具备最高的正常工做时间和可用性,主要用于MySQL Cluster 分布式集群环境,
  • CSV
    CSV存储引擎使用逗号分隔值格式将数据存储在文本文件中。可使用CSV引擎以CSV格式导入和导出其余软件和应用程序之间的数据交换
  • BLACKHOLE
    -黑洞存储引擎接受但不存储数据,检索老是返回一个空集。做为中间代理使用,该功能可用于分布式数据库设计,数据自动复制,但不是本地存储,例如用于主从复制的中间代理
  • example
    “stub”引擎,它什么都不作。可使用此引擎建立表,但不能将数据存储在其中或从中检索。目的是做为例子来讲明如何开始编写新的存储引擎

4.6 管理存储引擎

  • 查看mysql支持的存储引擎:
    show engines;

  • 查看当前默认的存储引擎:

       
       
       
       
       
    • 1
    MariaDB [(none)]> SHOW VARIABLES LIKE '%storage_engine%'
  • 设置默认的存储引擎:

       
       
       
       
       
    • 1
    • 2
    • 3
    vim /etc/my.conf [mysqld] default_storage_engine=InnoDB <==[mysqld]中增长系统此选项
  • 查看库中全部表使用的存储引擎
    Show table status from db_name;

       
       
       
       
       
    • 1
    • 2
    '查看hellodb数据库中表的引擎' MariaDB [(none)]> SHOW table STATUS FROM hellodb\G
  • 查看库中指定表的存储引擎

    1. 经过查看表状态信息获取
      show table status like ’ tb_name’;
           
           
           
           
           
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      '进入表所在数据库' MariaDB [(none)]> use hellodb '查询表students所用引擎' MariaDB [hellodb]> SHOW table STATUS LIKE 'students'\G *************************** 1. row *************************** Name: students 'Engine: InnoDB' <==存储引擎
    2. 经过查看表建立信息获取
      show create table tb_name;
           
           
           
           
           
      • 1
      • 2
      • 3
      MariaDB [hellodb]> SHOW CREATE table students; ......省略 ) 'ENGINE=InnoDB' AUTO_INCREMENT=26 DEFAULT CHARSET=utf8 |
  • 设置表的存储引擎:

    1. 建立表时,指定存储引擎
      CREATE TABLE tb_name(… ) ENGINE=InnoDB;
           
           
           
           
           
      • 1
      • 2
      '建立默认引擎为Innodb的表cc' MariaDB [db2]> CREATE TABLE cc(StuID int unsigned NOT NULL,Name varchar(50) NOT NULL) ENGINE=Innodb;
    2. 修改表存储引擎
      ALTER TABLE tb_name ENGINE=InnoDB;
           
           
           
           
           
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      '修改表cc的存储引擎为MyISAM' MariaDB [db2]> ALTER TABLE cc ENGINE=MyISAM; '查看修改效果' MariaDB [db2]> SHOW TABLE STATUS LIKE 'cc'\G *************************** 1. row *************************** Name: cc Engine: MyISAM

5. 服务器配置

  • mysql官方服务器配置表

    1. 官方地址
      https://dev.mysql.com/doc/refman/5.7/en/mysqld-option-tables.html
    2. 配置表格式
      在这里插入图片描述
    3. 标准表内容
      1. Cmd-Linev
        是否能够在命令行执行
      2. Option file
        服务器选项,能够写在配置文件中,一般来说链接符使用’-’,因为不少服务器选项同时也为变量因此也支持‘_’写法
      3. System Var
        是否能够作服务器变量,链接符使用’_’,能够用做临时修改,修改又分为Global(不论链接多少会话都有效)和Session(针对当前会话有效)级别,Both表示两个都支持
      4. Status Var
        状态变量,做为值来参考,不能够修改
      5. Dynamic
        是否支持动态,在不重启主机的状况下直接修改
  • mariadb官方服务器配置列表

    1. 官方地址
      https://mariadb.com/kb/en/library/full-list-of-mariadb-options-system-and-status-variables/
    2. 格式
      --aria-block-size:带–表示为服务器选项,
      aria_block_size:表示同时为变量
      在这里插入图片描述 点击蓝色部分,进入详细描述
           
           
           
           
           
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      aria_block_size <==配置选项|变量 Description: Block size to be used for Aria index pages. Changing this requires dumping, deleting old tables and deleting all log files, and then restoring your Aria tables. If key lookups take too long (and one has to search roughly 8192/2 by default to find each key), can be made smaller, e.g. 2048 or 4096. Commandline: --aria-block-size=# <==是否支持命令行 Scope: Global <==变量范围级别 Dynamic: No <==是否支持动态修改 Data Type: numeric <==数据类型 Default Value: 8192 <==默认值
  • 系统变量

    1. 系统变量查询

      1. 格式
        支持模糊查询,默认为SESSION级别的
        SHOW VARIABLES [LIKE 'Variable_name']
        查GLOBAL级别的变量
        SHOW GLOBAL VARIABLES [LIKE 'Variable_name]'
      2. 示例
               
               
               
               
               
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        '列出全部会话系统变量' MariaDB [(none)]> SHOW VARIABLES; '查找指定会话系统变量' MariaDB [(none)]>SHOW VARIABLESlike LIKE '%datadir%' ; +---------------+--------------+ | Variable_name | Value | +---------------+--------------+ | datadir | /data/mysql/ | <==变量的键值 +---------------+--------------+
      3. 常见的系统变量
        max_connections:容许最大并发链接数
               
               
               
               
               
        • 1
        • 2
        MariaDB [hellodb]> show variables like '%connect%'; | max_connections | 151 |
    2. 修改服务器变量的值:

      1. 获取设置SET帮助
        mysql> help SET
      2. 修改全局变量:仅对修改后新建立的会话有效;对已经创建的会话无效
        SET GLOBAL system_var_name=value
        SET @@global.system_var_name=value
               
               
               
               
               
        • 1
        • 2
        MariaDB [db2]> SET GLOBAL max_connections=500; MariaDB [db2]> SET @@GLOBAL.max_connections=600;
      3. 修改会话变量:
        SET [SESSION] system_var_name=value
        SET @@[session.] system_var_name=value
  • 状态变量(只读)
    用于保存mysqld运行中的统计数据的变量,不可更改

    1. 格式
      查看全局状态变量
      SHOW GLOBAL STATUS [LIKE ‘Variable_name’]
      查看会话状态变量
      SHOW [SESSION] STATUS [LIKE ‘Variable_name’]

    2. 示例
      uptime:查看服务器启动时间

           
           
           
           
           
      • 1
      MariaDB [(none)]> show status like 'uptime';

      Com_select:查看使用查询的次数

           
           
           
           
           
      • 1
      • 2
      MariaDB [hellodb]> show status like '%select%'; | Com_select | 4 | <==查询计数器

      Com_insert:查看插入计数器

           
           
           
           
           
      • 1
      • 2
      MariaDB [hellodb]> show status like '%insert%'; | Com_insert | 1 |

      Threads_connected:查看多少人正在链接数据库,Threads为进程项

           
           
           
           
           
      • 1
      • 2
      • 3
      MariaDB [hellodb]> show status like '%Threads%'; | Threads_connected | 1 | <==正在链接的 | Threads_running | 1 | <==正在运行的
  • 服务器选项

    1. 查看服务器选项
      获取mysqld的可用选项列表
           
           
           
           
           
      • 1
      [root@hai7-8 mysql]$mysqld --verbose --help
      获取默认设置
           
           
           
           
           
      • 1
      [root@hai7-8 mysql]$mysqld --print-defaults
      若是mysqld不在PATH变量中,须要写绝对路径
           
           
           
           
           
      • 1
      • 2
      • 3
      • 4
      • 5
      查看进程,找到服务绝对路径 [root@hai7-8 ~]$ps aux|grep mysqld [root@hai7-8 ~]$/usr/libexec/mysqld --verbose --help 获取默认设置 [root@hai7-8 ~]$/usr/libexec/mysqld --print-defaults
    2. 设置服务器选项方法
      1. 在命令行中设置:
        [root@hai7-8 ~]$./mysqld_safe –-skip-name-resolve=1;
      2. 在配置文件my.cnf中设置:
               
               
               
               
               
        • 1
        • 2
        • 3
        [root@hai7-8 ~]$vim /etc/my.cnf [mysqld] skip_name_resolve=1 <==增长在mysqld块里
    3. 示例
      设置默认将表数据独立存放为单个文件
           
           
           
           
           
      • 1
      • 2
      • 3
      vim /etc/my.conf [mysqld] innodb_file_per_table
      拒绝将ip地址反向解析成名字
      将ip地址反向解析成名字可能会致使链接失败,例如集群操做时
           
           
           
           
           
      • 1
      • 2
      • 3
      vim /etc/my.conf [mysqld] skip-name-resolve=on <==便是选项又是变量
  • 服务器变量SQL_MODE

    1. 做用
      对其设置能够完成一些约束检查的工做,可分别进行全局的设置或当前会话的设置,参看:https://mariadb.com/kb/en/library/sql-mode/
    2. 常见MODE:
      1. NO_AUTO_CREATE_USER
        禁止GRANT(受权)建立密码为空的用户
      2. NO_ZERO_DATE
        在严格模式,不容许使用‘0000-00-00’的时间
      3. ONLY_FULL_GROUP_BY
        对于GROUP BY聚合操做,若是在SELECT中的列,没有在GROUP BY中出现,那么将认为这个SQL是不合法的
      4. NO_BACKSLASH_ESCAPES
        反斜杠“\”做为普通字符而非转义字符
      5. PIPES_AS_CONCAT
        将"||"视为链接操做符而非“或运算符”
  • 注意事项

    1. 其中有些参数支持运行时修改,会当即生效;有些参数不支持,且只能经过修改配置文件,并重启服务器程序生效;有些参数做用域是全局的,且不可改变;有些能够为每一个用户提供单独(会话)的设置
    2. 纯变量不能放在配置文件中的,会影响启动,例如character_set_results

6. 查询缓存

  • 从工做流程看MySQL架构
    数据库自己是不能和磁盘直接交流的,是经过存储引擎将指令发送给内核,经过内核和文件系统打交道,再将数据写到磁盘文件中
    在这里插入图片描述

    1. connectors
      各类语言提供的链接数据库的能力
    2. connection pool
      数据库中的链接池,提供了验证身份,线程复用(系统判断线程使用次数过多,自动销毁),链接限制,内存检查,缓存功能使用
    3. SQL interface
      将用户提交的SQL语句进行检查,经过检查,则将SQL语句翻译给系统,进行执行
    4. parser
      解析语句,验证访问对象权限
    5. optimizer
      优化过程,访问路径
    6. Caches & Buffers
      缓存与缓冲区的使用,例如写入数据库时,先缓冲至缓冲区而后批量写入
    7. Pluggable Storage Englnes
      写入时用到的存储引擎,不一样的引擎在硬件设备上保存数据的方式是不一样的
    8. Files&Logs:
      日志
    9. Management Services & Utilltles:
      辅助管理工具
  • 查询的执行路径
    在这里插入图片描述

    1. 客户端软件链接数据库
    2. 链接数据库使用通讯协议,基于mysql的IPA接口开发出来的通讯协议
    3. 创建通讯后验证帐号等安全检查,经过检查后用户发出请求,好比select,请求先到达mysql的查询缓存,若是缓存中有,直接返回结果
    4. 若是缓存中没有,将请求发送给解析器,生成解析树,通过预处理生成新的解析树
    5. 查询优化器将新的解析树中进行查询优化
    6. 执行计划,经过优化查询,判断出最佳查询路径,好比是否利用索引,利用那种索引等
    7. 将执行计划提交给存储引擎,经过存储引擎链接数据库进行访问,访问的数据是以块的形式存放的,大小为16k
  • 查询缓存(只负责查询的缓存)

    1. 查询缓存(Query Cache )原理:
      缓存SELECT操做或预处理查询的结果集和SQL语句,当有新的SELECT语句或预处理查询语句请求,先去查询缓存,判断是否存在可用的记录集
    2. 判断标准
      与缓存的SQL语句,是否彻底同样,区分大小写(缓存中的数据,是根据查询的SQL语句,进行哈希运算,放在缓存中,因此若是大小写不一样,哈希值就不一样,在缓存中是查询不到结果的)
    3. 优缺点
      1. 不须要对SQL语句作任何解析和执行,固然语法解析必须经过在先,直接从Query Cache中得到查询结果,提升查询性能
      2. 查询缓存的判断规则,不够智能,也即提升了查询缓存的使用门槛,下降其效率;
      3. 查询缓存的使用,会增长检查和清理Query Cache中记录集的开销
  • 哪些查询可能不会被缓存

    1. 查询语句中加了SQL_NO_CACHE参数,例如数据库数据已经更新,缓存中的数据为旧数据,能够加此参数跳过查询缓存
    2. 查询语句中含有得到值的函数(常常变化的值),包含自定义函数,如:NOW()
      CURDATE()、GET_LOCK()、RAND()、CONVERT_TZ()等
    3. 对系统数据库的查询:mysql、information_schema查询语句中使用SESSION级别变量或存储过程当中的局部变量
    4. 查询语句中使用了LOCK IN SHARE MODE、FOR UPDATE的语句,查询语句中相似SELECT …INTO 导出数据的语句
    5. 对临时表的查询操做;存在警告信息的查询语句;不涉及任何表或视图的查询语句;某用户只有列级别权限的查询语句
    6. 事务隔离级别为Serializable时,全部查询语句都不能缓存
  • 查询缓存相关的服务器变量

       
       
       
       
       
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    与缓存相关的变量 MariaDB [(none)]> SHOW VARIABLES LIKE 'query_cache%'; +------------------------------+----------+ | Variable_name | Value | +------------------------------+----------+ | query_cache_limit | 1048576 | | query_cache_min_res_unit | 4096 | | query_cache_size | 33554432 | | query_cache_strip_comments | OFF | | query_cache_type | ON | | query_cache_wlock_invalidate | OFF | +------------------------------+----------+
    1. query_cache_min_res_unit
      查询缓存中内存块的最小分配单位,默认4k,较小值会减小浪费,但会致使更频繁的内存分配操做,较大值会带来浪费,会致使碎片过多,内存不足
    2. query_cache_limit
      单个查询结果能缓存的最大值,默认为1M,对于查询结果过大而没法缓存的语句,建议使用SQL_NO_CACHE
    3. query_cache_size
      查询缓存总共可用的内存空间;单位字节,必须是1024的整数倍,最小值40KB,低于此值有警报,默认为0
      以系统变量修改,仅支持以k为单位
           
           
           
           
           
      • 1
      MariaDB [hellodb]> set global query_cache_size=33554432;
      在配置文件中修改支持以M为单位
           
           
           
           
           
      • 1
      • 2
      • 3
      [root@hai7-8 ~]$vim /etc/my.cnf [mysqld] query_cache_size=30M
    4. query_cache_wlock_invalidate
      若是某表被其它的会话锁定,是否仍然能够从查询缓存中返回结果,默认值为OFF,表示能够在表被其它会话锁定的场景中继续从缓存返回数据;ON则表示不容许。其余事务在修改表时上锁,若是这时候搜索,可能获得的结果是脏数据。
    5. query_cache_type:
      是否开启缓存功能,取值为ON, OFF, DEMAND
      1. query_cache_type的值为OFF或0时,查询缓存功能关闭
      2. query_cache_type的值为ON或1时,查询缓存功能打开,SELECT的结果符合缓存条件即会缓存,不然,不予缓存,显式指定SQL_NO_CACHE,不予缓存,此为默认值
      3. query_cache_type的值为DEMAND或2时,查询缓存功能按需进行,显式指定SQL_CACHE的SELECT语句才会缓存;其它均不予缓存
  • SELECT语句的缓存控制

    1. SQL_CACHE: 显式指定存储查询结果于缓存之中
    2. SQL_NO_CACHE: 显式查询结果不予缓存
  • 参看文献
    https://mariadb.com/kb/en/library/server-system-variables/#query_cache_type
    https://dev.mysql.com/doc/refman/5.7/en/query-cache-configuration.html

  • 优化查询缓存
    在这里插入图片描述

    1. 命中率是否能够接受
      命中率就是屡次查询,有几回查询是在缓存中查到的
      1. 若是能够接受,那就不用优化
      2. 不能接受,进入第2大项判断
    2. 判断是否大部分查询结果没法缓存
      1. 大部分没法缓存,判断是否 query_cache_limit是否设置太小
        1. 不是此缘由则结束优化
        2. 单个缓存值设定过小,增大此值
      2. 大部分能够缓存,进入第3项判断
    3. 判断是否发生了许多验证工做(好比数据是否有效)
      1. 是,则去判断缓存是否被碎片化(内存最小单位设置不合理,形成多碎片)
        1. 是,经过重设块大小,或者清理碎片来优化
        2. 否,则判断是否有不少由于内存太低而发生的修复工做
          1. 是,则调节缓存大小
          2. 否,则判断是否有不少更新语句
            1. 是,结束优化,由于负载并不适合缓存
            2. 否,结束优化,有其余东西配置错误
      2. 否,进入第4项判断
    4. 判断缓存是否启用
      1. 是,多是该指令历来没有缓存过
      2. 否,启动缓存功能
  • 查询缓存的状态变量,与存储引擎无关,是系统的缓存变量

    1. 查询缓存相关的状态变量:
      SHOW GLOBAL STATUS LIKE ‘Qcache%’;
           
           
           
           
           
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      MariaDB [hellodb]> SHOW GLOBAL STATUS LIKE 'Qcache%'; +-------------------------+----------+ | Variable_name | Value | +-------------------------+----------+ | Qcache_free_blocks | 1 | | Qcache_free_memory | 33536824 | | Qcache_hits | 0 | | Qcache_inserts | 2 | | Qcache_lowmem_prunes | 0 | | Qcache_not_cached | 28 | | Qcache_queries_in_cache | 0 | | Qcache_total_blocks | 1 | +-------------------------+----------+
      1. Qcache_free_blocks:
        处于空闲状态Query Cache中内存Block 数
      2. Qcache_total_blocks:
        Query Cache 中总Block ,当Qcache_free_blocks相对此值较大时,可能用内存碎片,执行FLUSH QUERY CACHE清理碎片
      3. Qcache_free_memory:
        处于空闲状态的Query Cache 内存总量
      4. Qcache_hits:
        Query Cache 命中次数
      5. Qcache_inserts:
        向Query Cache 中插入新的Query Cache 的次数,即没有命中的次数
      6. Qcache_lowmem_prunes:
        0记录有多少条查询由于内存不足而被移除出查询缓存
      7. Qcache_not_cached:
        没有被Cache 的SQL 数,包括没法被Cache 的SQL 以及因为query_cache_type设置的不会被Cache 的SQL语句
      8. Qcache_queries_in_cache:
        在Query Cache 中的SQL 数量
  • 命中率和内存使用率估算

    1. 查询缓存中内存块的最小分配单位query_cache_min_res_unit:
           
           
           
           
           
      • 1
      (query_cache_size - Qcache_free_memory) / Qcache_queries_in_cache
    2. 查询缓存命中率
           
           
           
           
           
      • 1
      Qcache_hits/ ( Qcache_hits+ Qcache_inserts) * 100%
    3. 查询缓存内存使用率
           
           
           
           
           
      • 1
      (query_cache_size–qcache_free_memory) / query_cache_size* 100%
  • InnoDB存储引擎的缓冲池:
    一般InnoDB存储引擎缓冲池的命中不该该小于99%

    1. 查看相关状态变量
           
           
           
           
           
      • 1
      MariaDB [(none)]> SHOW GLOBAL STATUS LIKE 'innodb%read%'\G
    2. 经常使用状态变量描述
      1. Innodb_buffer_pool_reads:
        表示从物理磁盘读取页的次数
      2. Innodb_buffer_pool_read_ahead:
        预读的次数
      3. Innodb_buffer_pool_read_ahead_evicted:
        预读页,可是没有读取就从缓冲池中被替换的页数量,通常用来判断预读的效率
      4. Innodb_buffer_pool_read_requests:
        从缓冲池中读取页次数
      5. Innodb_data_read:
        总共读入的字节数
      6. Innodb_data_reads:
        发起读取请求的次数,每次读取可能须要读取多个页
    3. 相关计算
      在这里插入图片描述

7 提升数据库性能-索引

7.1 索引概述

  • 索引做用方式
    将索引定义在查找时做为查找条件的字段(如主键),将本来无序存放在磁盘存储器上的数据,转变为树状结构,按索引定义排序,以达到快速获得目标数据的功能;索引实如今存储引擎,与数据库和存储引擎密切相关,存储引擎不一样,支持的索引页大相径庭
  • 优势:
    1. 索引能够下降服务须要扫描的数据量,减小了IO次数
    2. 索引能够帮助服务器避免排序和使用临时表
    3. 索引能够帮助将随机I/O转为顺序I/O
  • 缺点:
    1. 占用额外空间
    2. 影响插入速度,平衡树结构要维持在一个正确状态,增删改数据都会改变平衡树各节点中的索引数据内容,数据库管理系统(DBMS)就会从新梳理树的结构,确保正确

7.2 索引结构

  • B-TREE:与二叉树相关

    1. 二叉树
      在这里插入图片描述

      1. 二叉树是递归定义的,每一个节点最多分两个叉

        1. 最上边的为根节点
        2. 最下边的为叶子节点
        3. 中间的所有为分支节点
      2. 查询顺序为:例如查询6号
        从根开始查,根为5号比6小,因此从右边开始查找,第二层为8比6大,因此从左分支走到第三层 找到7比6大,再从左边找获得6。就上图而言,找到6须要访问4次I/O

  • B-TREE索引
    在这里插入图片描述

    1. 优化二叉树,下降I/O次数,即访问磁盘的次数,在每层放两个数据,减小层数
    2. 在B-TREE中,每一个节点放2个数据,最多能够有3各分支,
    3. 节点中的指针P1指向比此区间大的下一层节点,指针P2指向在此区间范围的下一层节点,指针P3指向比此区间小的下一层节点
    4. 特征
      1. 关键字分布在整棵树中
      2. 任何一个关键字出现且只出如今一个结点中
      3. 搜索有可能在非叶子结点结束
    5. 缺点:
      叶子节点之间没有联系,若是要查范围数据,好比10号到30号之间的数据,须要重复从根节点开始查询
  • B+TREE
    在这里插入图片描述

    1. 特征

      1. 只有叶子节点存放数据,其余节点只放索引,分支节点不放数据,一样的块大小能够存放更多的索引,减小整个树的层次
      2. 在B+Tree的每一个叶子节点增长一个指向相邻叶子节点的指针,提升了区间访问性能
      3. 顺序存储,每个叶子节点到根结点的距离是相同的,查询效率稳定
    2. 可使用B-Tree索引的查询类型:

      1. 全值匹配:精确全部索引列
        如:姓wang,名xiaochun,年龄30
      2. 匹配最左前缀:即只使用索引的第一列
        如:姓wang
      3. 匹配列前缀:只匹配一列值开头部分,
        如:姓以w开头的
      4. 匹配范围值:
        如:姓ma和姓wang之间
      5. 精确匹配某一列并范围匹配另外一列
        如:姓wang,名以x开头的
    3. B-Tree索引的限制

      1. 若是不从最左列开始,则没法使用索引
        如:组合键为name+city,查找city为某地的用户,是没法使用索引的,由于city是针对name排序后,在name的基础上再排序,单个city是没有顺序的
      2. 不能跳过索引中的列
        如:例如查看某人来自哪一个城市,直接查城市是不能匹配的
      3. 若是查询中某个列是为范围查询,那么其右侧的列都没法再使用索引
        如:姓名以a开头的全部人,若是加上右侧city的索引,就会漏掉一部分a
  • Hash索引
    基于哈希表实现,只有精确匹配索引中的全部列的查询才有效,存储引擎会根据全部的索引计算出一个哈希值,哈希索引将全部的哈希值存储在索引中,索引自身只存储索引列对应的哈希值和数据指针,索引结构紧凑,查询性能好

    1. 适用场景:
      1. 只支持等值比较查询,包括=, <=>, IN()
      2. Memory存储引擎支持显式hash索引,InnoDB和MyISAM存储引擎不支持
    2. 不适合使用hash索引的场景:
      1. 不适用于顺序查询
        hash索引中存放哈希值和指针,而哈希值与原值不必定相同,所 以不能用来排序
      2. 不支持模糊匹配
      3. 不支持范围查询
      4. 不支持部分索引列匹配查找
        如A,B列索引,只查询A列索引无效
  • 特别提示

    1. 索引列的顺序和查询语句的写法应相匹配,才能更好的利用索引
    2. 为优化性能,可能须要针对相同的列但顺序不一样建立不一样的索引来知足不一样类型的查询需求

7.2 索引分类

  • 地理空间索引(Geospatial indexing ):
    MyISAM支持地理空间索引,可使用任意维度组合查询,使用特有的函数访问,经常使用于作地理数据存储,使用很少
    InnoDB从MySQL5.7以后也开始支持

  • 全文索引(FULLTEXT):
    先定义一个词库,而后在文章中查找每一个词条(term)出现的频率和位置,把这样的频率和位置信息按照词库的顺序概括,这样就至关于对文件创建了一个以词库为目录的索引,这样查找某个词的时候就能很快的定位到该词出现的位置
    InnoDB从MySQL 5.6以后也开始支持

  • 聚簇和非聚簇索引、二级(辅助)索引
    在这里插入图片描述

    1. 聚簇索引(Clustered Index),数据和索引在一个文件中,例如INNODB

      1. 特征
        1. 表数据按照索引的的顺序存储,也就是说索引与表中的记录物理顺序一致,
        2. 对于汇集索引,叶子结点即存储了真实的数据行,再也不有另外单独的数据页。
        3. 在一张表上最多只能建立一个汇集索引,由于真实数据的物理顺序只能有一种,系统默认会将主键设置为聚簇索引
      2. 聚簇索引的二级索引:
        叶子节点不会保存引用的行的物理位置,而是保存了行的主键,经过二级索引查找行,存储引擎须要找到二级索引的叶子节点得到对应的主键值,而后根据这个值去聚簇索引中查找到对应的行。
      3. 优势
        1. 数据与叶子节点存储在一块儿,和主键一块儿载入内存中,找到节点就能够当即返回数据,只按主键搜索来讲,获取速度快
        2. 使用覆盖索引扫描的查询能够直接使用节点中的主键值
      4. 缺点
        1. 插入速度严重依赖于插入顺序,若是不是按照主键顺序加载数据,那么在加载完成后最好使用OPTIMIZE TABLE命令从新组织一下表
        2. 更新聚簇索引列的代价很高,由于会强制InnoDB将每一个被更新的行移动到新的位置
        3. 基于聚簇索引的表在插入新行,或者主键被更新致使须要移动行的时候,可能面临“页分裂”的问题
        4. 聚簇索引可能致使全表扫描变慢,尤为是行比较稀疏,或者因为页分裂致使数据存储不连续的时候
        5. 二级索引包含主键列,比较大,并且须要通过两次B-TREE
    2. 非聚簇索引(Non- Clustered Index),索引和数据独立存放
      例如mysql数据库使用的MyISAM存储引擎,生成3个文件,分别存放索引、表结构、数据

      1. 特征
        1. 表数据存储顺序与索引顺序无关。
        2. 对于非汇集索引,叶结点包含索引字段值及指向数据页数据行的逻辑指针,其行数量与数据表行数据量一致
        3. 非聚簇索引能够有多个
      2. 非聚簇索引的二级索引:
        主键索引和二级索引区别不大,只是主键索引是惟一的存放的是主键,二级索引存放的是辅助键
  • 稠密索引、稀疏索引
    是否索引了每个数据项

    1. 稠密索引
      每一个记录都有一个索引项,记录在数据区存放是任意的,但索引是按序的
    2. 稀疏数据线
      将全部数据记录关键字值分红许多组,每组一个索引项
  • 简单索引、组合索引

    1. 单一索引
      索引列为一列的状况,即新建索引的语句只实施在一列上

    2. 复合索引,
      由多列建立的索引称为复合索引,在符合索引中的前导列必须出如今where条件中,索引才会被使用

  • 主键索引与惟一键索引

    1. 惟一索引
      惟一索引比较好理解,不容许具备索引值相同的行,这样的索引选择性是最好的

    2. 主键索引
      主键索引就是惟一索引,不过主键索引是在建立表时就建立了,惟一索引能够随时建立。

    3. 区别

      1. 主键是主键约束+惟一索引
      2. 主键必定包含一个惟一索引,但惟一索引不是主键
      3. 惟一索引列容许空值,但主键列不容许空值
      4. 一个表只能有一个主键,但能够有多个惟一索引
  • 覆盖索引
    select的数据列只用从索引中就可以取得,没必要读取数据行,换句话说查询列要被所建的索引覆盖

  • 冗余和重复索引:

    1. 冗余索引:(A),(A,B)
      复合索引A,B已经对A进行排序,再创建A索引没有意义
    2. 重复索引:已经有索引,再次创建索引
      针对相同的字段重复创建,例如字段age,先创建idx_age1,又在其上创建idx_age2

7.4 索引优化策略:

  1. 独立地使用列
    尽可能避免其参与运算,独立的列指索引列不能是表达式的一部分,也不能是函数的参数,在where条件中,始终将索引列单独放在比较符号的一侧
       
       
       
       
       
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    '创建索引在字段age上' MariaDB [hellodb]> create index index_age ON students(age); 'age+5就是指索引参与运算,混在一块儿计算是没法利用索引的' MariaDB [hellodb]> select * from students where age+5=25; +-------+--------------+-----+--------+---------+-----------+ | StuID | Name | Age | Gender | ClassID | TeacherID | +-------+--------------+-----+--------+---------+-----------+ | 9 | Ren Yingying | 20 | F | 6 | NULL | | 22 | Xiao Qiao | 20 | F | 1 | NULL | +-------+--------------+-----+--------+---------+-----------+ '若是必定要运算,应该讲运算放在=右边' MariaDB [hellodb]> select * from students where age=20+5;
    1. 左前缀索引
      构建索引时指定字段字符数,具体长度要经过索引选择性来评估
      例如:将名字做为索引时,表内名字都在10个字符以上,通过评估仅使用前3个字符就能够达到区别各行的目的,就能够考虑左前缀索引,限定为3各字符
    2. 多列索引
      AND操做时更适合使用多列索引,而非为每一个列建立单独的索引
    3. 选择合适的索引列顺序
      无排序和分组时,将选择性最高放左侧
    4. 只要列中含有NULL值,就最好不要在此例设置索引,复合索引若是有NULL值,此列在使用时也不会使用索引
    5. 尽可能使用短索引,若是能够,应该制定一个前缀长度
    6. 对于常常在where子句使用的列,最好设置索引
    7. 对于有多个列where或者order by子句,应该创建复合索引
    8. 对于like语句,以%或者‘-’开头的不会使用索引,以%结尾会使用索引
    9. 尽可能不要使用not in和<>操做
  • SQL语句性能优化
    1. 查询时,能不要*就不用*,尽可能写全字段名
    2. 大部分状况链接效率远大于子查询
    3. 多表链接时,尽可能小表驱动大表,即小表join 大表
    4. 在有大量记录的表分页时使用limit
    5. 对于常用的查询,能够开启缓存
    6. 多使用explain和profile分析查询语句
    7. 查看慢查询日志,找出执行时间长的sql语句优化
</div>
					<link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-7f770a53f2.css" rel="stylesheet">
            </div>
相关文章
相关标签/搜索