随笔
物化视图
select user();
select now();
select version();
ifnull
数据库奔溃后内存没写到内存中,重启时重做
1、视图
视图:VIEW
虚表,在调用时保存有实表的查询结果 ;在调用视图时进行后台调用查询语句进行查询;可
以当作表来对待;
创建方法:
CREATE VIEW view_name [(column_list)]
AS select_statement [WITH
[CASCADED | LOCAL] CHECK OPTION]
删除视图:
DROP VIEW [IF EXISTS]
view_name [, view_name] ...
[RESTRICT | CASCADE]
视图中的数据事实上存储于“基表”中,因此,其修改操作也
会针对基表实现;其修改操作受基表限制
扩展:物化视图是真实存在的表,将查询结果返回到表中,即存入了磁盘;调用此视图时的效率比较高,因为不用进行查询;实质上是以磁盘空间换取效率的提升;
本点命令:
mysql 登录无密码数据库
show databases;
use hellodb2;
show tables;
select from students
select name,age,gender from students where gender = 'M'
create view view_students as select name,age,gender from students where gender = 'M'
select from view_students; 创建视图
update view_students set name='wang' where age=22; 通过视图修改真正的表
create view view_students1 as select name,age from students where gender='M';
insert view_students1 values('mage',28);
select from view_students1;
select from students;
desc students; 查看表students的创建时的描述信息
drop view view_students1;
desc view_students;
2、函数
函数:系统函数和自定义函数
系统函数:
https://dev.mysql.com/doc/refman/5.7/en/func-op-summary-ref.html 先前访问地址有问
题,要填对;
自定义函数 (user-defined function UDF)
创建和删除自定义函数语法:
创建UDF:
CREATE [AGGREGATE] FUNCTION function_name(parameter_name type,
[parameter_name type,...])
RETURNS {STRING|INTEGER|REAL} runtime_body
说明: 参数可以有多个,也可以没有参数
必须有且只有一个返回值
本点常用命令:
select now(); 查看当前系统的时间
select curdate(); 只显示日期
select curtime(); 只显示时间
select version(); 查看当前系统的版本
select user(); 查看当前的用户
select name,ifnull(classid,'noclass') from students; 验证ifnull函数的用法,classid为空
就返回noclass,不为空就返回classid;
3、自定义函数
删除UDF:
DROP FUNCTION function_name
调用自定义函数语法:
SELECT function_name(parameter_value,...)
示例:创建简单的无参UDF
CREATE FUNCTION simpleFun() RETURNS VARVHAR(20) RETURN "Hello World!";
本点常用命令:
create function simplefun() returns varchar(20) return "HelloWorld!!"; 创建自定义函数
select simplefun(); 调用自定义函数
create function deleteById(uid smallint unsigned) returns int begin delete from students
where stuid=uid; return (select count(stuid) from students);end// 创建有参数的自定义函数
4、自定义函数
示例: DELIMITER //
CREATE FUNCTION IF EXIST deleteById(uid
SMALLINT UNSIGNED)
RETURNS VARCHAR(20)
BEGIN
DELETE FROM students WHERE stuid = uid;
RETURN (SELECT COUNT(id) FROM students);
END//
5、自定义函数
自定义函数中定义局部变量语法:
DECLARE 变量1[,变量2,... ]变量类型 [DEFAULT 默认值]
说明:局部变量的作用范围是在BEGIN...END程序中,而且定义局 部变量语句必须在
BEGIN...END的第一行定义
示例:
DELIMITER //
CREATE FUNCTION addTwoNumber(x SMALLINT
UNSIGNED, Y SMALLINT UNSIGNED)
RETURNS SMALLINT
BEGIN
DECLARE a, b SMALLINT UNSIGNED DEFAULT 10;
SET a = x, b = y;
RETURN a+b;
END//
6、自定义函数
为变量赋值语法:
SET parameter_name = value[,parameter_name = value...]
SELECT INTO parameter_name
示例:
...
DECLARE x int;
SELECT COUNT(id) FROM tdb_name INTO x;
RETURN x;
END//
7、存储过程
创建存储过程:
CREATE PROCEDURE sp_name ([ proc_parameter [,proc_parameter ...]])
routime_body
其中:proc_parameter : [IN|OUT|INOUT] parameter_name type
其中IN表示输入参数,OUT表示输出参数,INOUT表示既 可以输入也可以输出;
param_name表示参数名称;type表示 参数的类型 ;
8、存储过程
调用存储过程:
CALL sp_name ([ proc_parameter [,proc_parameter ...]])
CALL sp_name
说明:当无参时,可以省略"()",当有参数时,不可省略"()”
存储过程修改:
ALTER语句修改存储过程只能修改存储过程的注释等无关紧 要的东西,不能修改存储过程体,
所以要修改存储过程,方法就 是删除重建;
删除存储过程:
DROP PROCEDURE [IF EXISTS] sp_name
9、存储过程示例
创建无参存储过程:
delimiter //
CREATE PROCEDURE showTime()
BEGIN
SELECT now();
END//
delimiter ;
CALL showTime;
10、存储过程示例
创建含参存储过程:只有一个IN参数
delimiter //
CREATE PROCEDURE seleById(IN id SMALLINT UNSIGNED)
BEGIN
SELECT * FROM students WHERE stuid = id;
END//
delimiter ;
call seleById(2);
此实验已验证
11、存储过程示例
delimiter //
CREATE PROCEDURE dorepeat(p1 INT)
BEGIN
SET @x = 0;
REPEAT SET @x = @x + 1; UNTIL @x > p1 END REPEAT;
END //
delimiter ;
CALL dorepeat(1000);
SELECT @x;
12、存储过程示例
创建含参存储过程:包含IN参数和OUT参数
delimiter //
CREATE PROCEDURE deleteById(IN id SMALLINT UNSIGNED, OUT num
SMALLINT UNSIGNED)
BEGIN
DELETE FROM students WHERE stuid = id;
SELETE row_count() into num;
END//
delimiter ;
call seleById(2,@Line);
SELETE @Line;
说明:创建存储过程deleteById,包含一个IN参数和一个OUT 参数.调用时,传入删除的ID和保存
被修改的行数值的用户变 量@Line,select @Line;输出被影响行数.
13、存储过程
存储过程优势:
存储过程把经常使用的SQL语句或业务逻辑封装起来,预编译保存在数据库中,当需要时从数
据库中直接调用,省去了编译的过程
提高了运行速度
同时降低网络数据传输量 (用户通过传输函数名和参数进行访问,数据量变小)
存储过程与自定义函数的区别:
存储过程实现的过程要复杂一些,而函数的针对性较强
存储过程可以有多个返回值,而自定义函数只有一个返回值
存储过程一般独立的来执行,而函数往往是作为其他SQL语句的一部分来使用如select
存储过程一般用于专职的DBA进行自定义
14、流程控制
存储过程和函数中可以使用流程控制来控制语句的执行
流程控制:
IF:用来进行条件判断。根据是否满足条件,执行不同语句
CASE:用来进行条件判断,可实现比IF语句更复杂的条件判断
LOOP:重复执行特定的语句,实现一个简单的循环
LEAVE:用于跳出循环控制
ITERATE:跳出本次循环,然后直接进入下一次循环
REPEAT:有条件控制的循环语句。当满足特定条件时,就会跳出循环语句
WHILE:有条件控制的循环语句
15、触发器
触发器的执行不是由程序调用,也不是由手工启动,而是由事件来触发、 激活从而实现执行
创建触发器
CREATE
[DEFINER = { user | CURRENT_USER }]
TRIGGER trigger_name
trigger_time trigger_event
ON tbl_name FOR EACH ROW
trigger_body
说明:
trigger_name:触发器的名称
trigger_time:{ BEFORE | AFTER },表示在事件之前或之后触发
trigger_event::{ INSERT |UPDATE | DELETE },触发的具体事件
tbl_name:该触发器作用在表名
16、触发器示例
CREATE TABLE student_info (
stu_no INT(11) NOT NULL AUTO_INCREMENT,
stu_name VARCHAR(255) DEFAULT NULL,
PRIMARY KEY (stu_no)
);
CREATE TABLE student_count (
student_count INT(11) DEFAULT 0
);
INSERT INTO student_count VALUES(0);
17、触发器示例
示例:创建触发器,在向学生表INSERT数据时,学生数增加 ,DELETE学生时,学生数减少
CREATE TRIGGER trigger_student_count_insert
AFTER INSERT
ON student_info FOR EACH ROW
UPDATE student_count SET
student_count=student_count+1;
CREATE TRIGGER trigger_student_count_delete
AFTER DELETE ON student_info FOR EACH ROW
UPDATE student_count SET
student_count=student_count-1;
18、触发器
查看触发器
SHOW TRIGGERS
查询系统表information_schema.triggers的方式指定查询条件,查看指定的触发器信息。
USE information_schema;
SELECT * FROM triggers WHERE trigger_name='trigger_student_count_insert';
删除触发器
DROP TRIGGER trigger_name;
19、MySQL用户和权限管理
元数据数据库:mysql
系统授权表:
db, host, user
columns_priv, tables_priv, procs_priv, proxiespriv
用户账号:
'USERNAME'@'HOST':
@'HOST':
主机名;
IP地址或Network;
通配符:
%, : 172.16.%.%
19、用户管理
创建用户:CREATE USER
CREATE USER 'USERNAME'@'HOST' [IDENTIFIED BY 'password'];
默认权限:USAGE
用户重命名:RENAME USER
RENAME USER old_user_name TO new_user_name
删除用户:
DROP USER 'USERNAME'@'HOST‘
示例:删除默认的空用户
DROP USER ''@'localhost';
20、用户管理
修改密码:
mysql>SET PASSWORD FOR 'user'@'host' = PASSWORD(‘password');
mysql>UPDATE mysql.user SET password=PASSWORD('your_password') WHERE
clause; 此方法需要执行下面指令才能生效:mysql> FLUSH PRIVILEGES;
#mysqladmin -u root –poldpass password ‘newpass‘
忘记管理员密码的解决办法:
启动mysqld进程时,为其使用如下选项:
--skip-grant-tables --skip-networking
使用UPDATE命令修改管理员密码
关闭mysqld进程,移除上述两个选项,重启mysqld
21、MySQL权限管理
权限类别:
数据库级别
表级别
字段级别
管理类
程序类
22、MySQL用户和权限管理
管理类:
CREATE TEMPORARY TABLES
CREATE USER
FILE
SUPER
SHOW DATABASES
RELOAD
SHUTDOWN
REPLICATION SLAVE
REPLICATION CLIENT
LOCK TABLES
PROCESS
23、MySQL用户和权限管理
程序类: FUNCTION、PROCEDURE、TRIGGER
CREATE
ALTER
DROP
EXCUTE
库和表级别:DATABASE、TABLE
ALTER
CREATE
CREATE VIEW
DROP
INDEX
SHOW VIEW
GRANT OPTION:能将自己获得的权限转赠给其他用户
24、 MySQL用户和权限管理
数据操作:
SELECT
INSERT
DELETE
UPDATE
字段级别:
SELECT(col1,col2,...)
UPDATE(col1,col2,...)
INSERT(col1,col2,...)
所有权限:ALL PRIVILEGES 或 ALL
25、授权
参考:https://dev.mysql.com/doc/refman/5.7/en/grant.html
GRANT priv_type [(column_list)],... ON [object_type] priv_level TO 'user'@'host' [IDENTIFIED
BY 'password'] [WITH GRANT OPTION];
priv_type: ALL [PRIVILEGES]
object_type:TABLE | FUNCTION | PROCEDURE
priv_level: (所有库) | . | db_name. | db_name.tbl_name | tbl_name(当前库的表) |
db_name.routine_name(指定库的函数, 存储过程,触发器)
with_option: GRANT OPTION
| MAX_QUERIES_PER_HOUR count
| MAX_UPDATES_PER_HOUR count
| MAX_CONNECTIONS_PER_HOUR count
| MAX_USER_CONNECTIONS count
示例:GRANT SELECT (col1), INSERT (col1,col2) ON mydb.mytbl TO 'someuser'@'somehost';
本点常用命令:
GRANT SELECT (name), INSERT (age,gender) ON hellodb2.students TO 'test'@'%';
select * from user\G; 竖行查看user表的内容
show grants for 'test'; 显示用户test所拥有的权限
26、授权
回收授权:REVOKE priv_type [(column_list)] [, priv_type [(column_list)]] ... ON
[object_type] priv_level FROM user [, user] ... 示例:REVOKE DELETE ON testdb.* FROM
'testuser'@'%‘
查看指定用户获得的授权:
Help SHOW GRANTS
SHOW GRANTS FOR 'user'@'host';
SHOW GRANTS FOR CURRENT_USER[()];
注意:MariaDB服务进程启动时会读取mysql库中所有授权表至内存
(1) GRANT或REVOKE等执行权限操作会保存于系统表中,MariaDB的服务进程通常会自动
重读授权表,使之生效;
(2) 对于不能够或不能及时重读授权表的命令,可手动让MariaDB的服务进程重读授权表:
FLUSH PRIVILEGES; 重读授权表以刷新权限
本点常用命令:
revoke select on hellodb2.students from 'test'@'%'; 撤销授权
27、服务器配置
mysqld选项,服务器系统变量和服务器状态变量
https://dev.mysql.com/doc/refman/5.7/en/mysqld-option-tables.html
https://mariadb.com/kb/en/library/server-system-variables/
https://mariadb.com/kb/en/library/full-list-of-mariadb-options-system-and-status-variables/
获取运行中的mysql进程使用各服务器参数及其值
mysql> SHOW GLOBAL VARIABLES;
mysql> SHOW [SESSION] VARIABLES;
注意:其中有些参数支持运行时修改,会立即生效;有些参数不支持,且只能通过修改配置文
件,并重启服务器程序生效;有些参数作用域是全局的,且不可改变;有些可以为每个用户提供
单独(会话)的设置 ;
本点常用命令:
mysql -e 'show variables;'|wc -l 在数据库外边执行查看有多少变量
show variables like 'datadir'; 查看指定变量
show variables like 'log%'; 查看所有以log开头的变量
show status like 'uptime'; 查看指定状态变量
变量的类型:选项、系统变量、状态变量
28、服务器配置
设置服务器系统变量三种方法:
在命令行中设置:
shell> ./mysqld_safe --aria_group_commit="hard“
在配置文件my.cnf中设置:
aria_group_commit = "hard"
在mysql客户端使用SET命令:
SET GLOBAL aria_group_commit="hard";
常用命令:
/lib/systemd/system/mariadb.service 此文件是启动服务时的脚本
ExecStart=/usr/bin/mysqld_safe --basedir=/usr 此行是调用safe脚本和选项
vim /usr/bin/mysqld_safe 可以在此加选项进行修改启动配置
29、服务器端设置
修改服务器变量的值:
mysql> help SET 查看帮助
修改全局变量:仅对修改后新创建的会话有效;对已经建立的会话无效
mysql> SET GLOBAL system_var_name=value;
mysql> SET @@global.system_var_name=value;
修改会话变量:
mysql> SET [SESSION] system_var_name=value;
mysql> SET @@[session.]system_var_name=value;
状态变量(只读):用于保存mysqld运行中的统计数据的变量,不可更改
mysql> SHOW GLOBAL STATUS;
mysql> SHOW [SESSION] STATUS;
补充:
打开官网的系统变量标签页后如下字符的解释
dynamic:yes 意味着可以直接修改,不需要将变量写到文件重启服务生效
本点常用变量:
系统变量:autocommit、skip_networking、log_bin、skip_name_resolve、
状态变量:Com_select
本点常用命令:
show status like 'com_select'; 查询指定状态变量
show variables like 'port';
mysql -e 'show global status;'|grep Com_select 查询增长值记录
mysql -e 'show global status;'|grep Com_insert 查看插入的数量
30、SQL_MODE
服务器变量SQL_MODE:对其设置可以完成一些约束检查的工作,可分别 进行全局的设置或当前
会话的设置
常见MODE:
NO_AUTO_CREATE_USER
禁止GRANT创建密码为空的用户
NO_AUTO_VALUE_ON_ZERO
在自增长的列中插入0或NULL将不会是下一个自增长值
NO_BACKSLASH_ESCAPES
反斜杠“\”作为普通字符而非转义字符
PAD_CHAR_TO_FULL_LENGTH
启用后,对于CHAR类型将不会截断空洞数据
PAD_CHAR_TO_FULL_LENGTH
启用后,对于CHAR类型将不会截断空洞数据
PIPES_AS_CONCAT
将"||"视为连接操作符而非“或运算符”
本点常用命令:
create table t1(name char(5)); 建表
set sql_mode='traditional'; 设置模式
insert into t1 values('dsafasfasgsagfsa'); 设置传统模式后字符长度超出后不能进行
插入,而不只是之前的切断超出的部分;
31、MySQL架构
图的详解:
客户端用户通过一个应用程序访问数据库,而应用程序则是通过Connectors中的接口进行数
据库的访问,其中ODBC 是支持多中应用程序使用的;数据库服务器有一个连接池用于提供用户
的连接,并进行验证;连接池中的线程将已经连接断开的用户信息清除后是可以放到连接池进行
重用的;连接池进行并发连接数的限制;连接池进行内存和缓存的检查;连接成功后就访问SQL
interface进行SQL语句的接受与识别(语法上);Parser进行SQL语句转为二进制并进行权限等
的检查;Optimizer进行访问的优化如是否使用索引,选择最佳路径等;之后就将请求交给数据库
的引擎进行正式的访问;数据库引擎决定如何存储查找数据,数据库引擎也有一个存储数据的最
小单位block,mysql是每块16K,是文件系统块大小的整数倍,在mysql中block大小 只能编译源
代码进行修改,而oracle则可以通过重新建立数据库时用指令进行调整;在文件系统中cache是用
来读缓存,buffer是写缓冲区;
32、查询的执行路径
解释:当有人执行过同样的SQL语句时,就有了缓存信息,直接交给
数据库引擎进行查询操作;当没有人进行查询过,就进行解析找出好的路径形成解析树,然后进过预处理整理形成新的解析树,然后进行优化处理尽可能找出最佳路径,然后形成一个执行指令的计划交给数据库引擎进行处理;然后将处理的结果进行返回给缓存和客户端;
33、查询缓存
查询缓存( Query Cache )原理:
缓存SELECT操作或预处理查询的结果集和SQL语句,当有 新的SELECT语句或预处理
查询语句请求,先去查询缓存,判断 是否存在可用的记录集,判断标准:与缓存的SQL
语句,是否完 全一样,区分大小写 (用哈希值进行比对)
优缺点
不需要对SQL语句做任何解析和执行,当然语法解析必须通 过在先,直接从Query
Cache中获得查询结果,提高查询性能
查询缓存的判断规则,不够智能,也即提高了查询缓存的使用门槛,降低其效率;
查询缓存的使用,会增加检查和清理Query Cache中记录集 的开销
注意:查询的SQL语句要尽可能的规范才能高效的使用查询缓存;注意查询缓存的过期
问题;如果查询缓存没有被真正的使用起来如更改比较多缓存失效,那么反而比没有缓存还
要麻烦;
34、查询缓存
哪些查询可能不会被缓存
查询语句中加了SQL_NO_CACHE参数
使用此参数后查询不走缓存,对于某些特殊的扫描全表的操作和返回数据
量过大的操作是必要的;此参数通过help select命令可以看到
查询语句中含有获得值的函数,包含自定义函数,如:NOW() 、
CURDATE()、GET_LOCK()、RAND()、CONVERT_TZ()等 ;这些获得值时时刻
刻都在变化,缓存下来马上就会过期了,没有缓存的意义;
对系统数据库的查询:mysql、information_schema 查询语句 中使用
SESSION级别变量或存储过程中的局部变量
查询语句中使用了LOCK IN SHARE MODE、FOR UPDATE 的语句 查询语句
中类似SELECT …INTO 导出数据的语句
对临时表的查询操作;存在警告信息的查询语句;不涉及任何表 或视图的查询
语句;某用户只有列级别权限的查询语句;
如:select now();、select @x;set @x='hello';select @x;
事务隔离级别为Serializable时,所有查询语句都不能缓存
事务的隔离级别在后面要讲到
35、查询缓存
查询缓存相关的服务器变量
show variables like 'query%'; 通过此命令显示出来数据库中的变量
query_cache_min_res_unit: 查询缓存中内存块的最小分配单位,默 认4k,较小值
会减少浪费,但会导致更频繁的内存分配操作,较大值 会带来浪费,会导致碎片过多,
内存不足
query_cache_limit:单个查询结果能缓存的最大值,默认为1M,对于查询结果过
大而无法缓存的语句,建议使用SQL_NO_CACHE
query_cache_size:查询缓存总共可用的内存空间;单位字节,必须 是1024的整
数倍,最小值40KB,低于此值有警报 ;0默认为不限制
query_cache_wlock_invalidate:如果某表被其它的会话锁定,是否仍然可以从查
询缓存中返回结果, 默认值为OFF,表示可以在表被其 它会话锁定的场景中继续从缓
存返回数据;ON则表示不允许
query_cache_type: 取值为ON(开启查询缓存功能), OFF, DEMAND
参看:https://dev.mysql.com/doc/refman/5.7/en/query-cache-configuration.html
36、查询缓存
SELECT语句的缓存控制
SQL_CACHE: 显式指定存储查询结果于缓存之中
SQL_NO_CACHE: 显式查询结果不予缓存
query_cache_type参数变量:
query_cache_type的值为OFF或0时,查询缓存功能关闭
query_cache_type的值为ON或1时,查询缓存功能打开, SELECT的结果符合缓存
条件即会缓存,否则,不予缓存, 显式指定SQL_NO_CACHE,不予缓存,此为默认值
query_cache_type的值为DEMAND或2时,查询缓存功能 按需进行,显式指定
SQL_CACHE的SELECT语句才会缓存 ;其它均不予缓存
37、优化查询缓存
注意:影响命中率(利用查询缓存的频率)的各种因数
38、查询缓存
查询缓存相关的状态变量
SHOW GLOBAL STATUS LIKE ‘Qcache%';
Qcache_free_blocks:处于空闲状态的Query Cache中内存 Block数
Qcache_free_memory:处于空闲状态的Query Cache 内存总量
Qcache_hits:Query Cache 命中次数;包含下面的新插入的没有命中的次数
Qcache_inserts:向 Query Cache 中插入新的 Query Cache 的次 数,即没有命中的次数
Qcache_lowmem_prunes:当 Query Cache 内存容量不够,需要删除老的 Query Cache
以给新的 Cache 对象使用的次数
Qcache_not_cached:没有被 Cache 的 SQL 数,包括无法被 Cache 的 SQL 以及由于
query_cache_type 设置的不会被 Cache 的 SQL语句
Qcache_queries_in_cache:在 Query Cache 中的 SQL 数量
Qcache_total_blocks:Query Cache 中总的 Block
39、命中率
命中率和内存使用率估算
query_cache_min_res_unit ≈(query_cache_size - Qcache_free_memory) /
Qcache_queries_in_cache
查询缓存命中率 ≈ (Qcache_hits – Qcache_inserts) / Qcache_hits 100%
查询缓存内存使用率 ≈ (query_cache_size – qcache_free_memory) / query_cache_size 100%
40、InnoDB存储引擎
InnoDB存储引擎的缓冲池:
通常InnoDB存储引擎缓冲池的命中不应该小于99%
查看相关状态变量:
show global status like 'innodb%read%'\G
Innodb_buffer_pool_reads: 表示从物理磁盘读取页的次数
Innodb_buffer_pool_read_ahead: 预读的次数
Innodb_buffer_pool_read_ahead_evicted: 预读页,但是没有读取就从缓冲池中被替换的页
数量,一般用来判断预读的效率
Innodb_buffer_pool_read_requests: 从缓冲池中读取页次数
Innodb_data_read: 总共读入的字节数
Innodb_data_reads: 发起读取请求的次数,每次读取可能需要读取多个页
41、存储引擎
Innodb缓冲池命中率计算:
42、索引
索引是特殊数据结构:定义在查找时作为查找条件的字段
优点:提高查询速度,缺点:占用额外空间,影响插入速度
索引实现在存储引擎
索引类型:
聚簇(集)索引、非聚簇索引:数据是否与索引存储在一起
主键索引、辅助索引
稠密索引、稀疏索引:是否索引了每一个数据项 ;树从上到下依次为稀疏索引到稠密索引;
B+ TREE、HASH、R TREE 后两种索引结构用的不多
简单索引、组合索引(多个 字段组合) 左前缀索引:取前面的字符做索引 覆盖索引:从索
引中即可取出要查
询的数据,性能高
43、聚簇和非聚簇索引,主键和二级索引
注意:聚簇索引是索引和数据放在一起,而非聚簇索引是索引id按顺序存放指向数据,磁盘数据中id为3可以先存放,然后可以存放id为1的数据,并不是按照id顺序连续空间存放;innodb主键会自动创建索引的;二级索引是先找到主键索引,然后通过主键索引进行数据的查找;MyISAM引擎表是三个文件包括定义文件、索引文件和数据文件;二级索引和主键索引的区别是看索引的存放顺序和数据的存放顺序是否一致;
44、B+TREE索引
45、索引B+tree
46、B-Tree索引
B+ Tree索引:顺序存储,每一个叶子节点到根结点的距离是相同的,如果在某一叶子大量增加
数据要进行数据整理使得树平衡,B即balance;左前缀索引,适合查询范围类的数据如按照字母顺序进行排序查找;
可以使用B-Tree索引的查询类型:
全值匹配:精确所有索引列,如:姓wang,名xiaochun, 年龄30
匹配最左前缀:即只使用索引的第一列,如:姓wang
匹配列前缀:只匹配一列值开头部分,如:姓以w开头的
匹配范围值:如:姓ma和姓wang之间 精确匹配某一列并范围匹配另一列:如:姓wang,名
以x开 头的
只访问索引的查询 :只以复合索引中的列作为查询条件
47、B-Tree索引
B-Tree索引的限制:
如果不从最左列开始,则无法使用索引:如:查找名为 xiaochun,或姓为g结尾
不能跳过索引中的列:如:查找姓wang,年龄30的,只能使用索引第一列
如果查询中某个列是为范围查询,那么其右侧的列都无法 再使用索引:如:姓wang,名x%,
年龄30,只能利用姓和名 上面的索引
特别提示:
索引列的顺序和查询语句的写法应相匹配,才能更好的利用索引
为优化性能,可能需要针对相同的列但顺序不同创建不同的索引来满足不同类型的查询需求
48、Hash索引
Hash索引:基于哈希表实现,只有精确匹配索引中的所有列 的查询才有效,索引自身只存储索引列对应的哈希值和数据指针,索引结构紧凑,查询性能好
只有Memory存储引擎支持显式hash索引
适用场景:
只支持等值比较查询,包括=, IN(), <=>
不适合使用hash索引的场景:
不适用于顺序查询:索引存储顺序的不是值的顺序
不支持模糊匹配
不支持范围查询
不支持部分索引列匹配查找:如A,B列索引,只查询A列索引 无效
49、索引
空间索引(R-Tree):
MyISAM支持空间索引,可以使用任意维度组合查询,使用特有的函数访问,常用于做地理
数据存储,使用不多
全文索引(FULLTEXT):
在文本中查找关键词,而不是直接比较索引中的值,类似搜索 引擎
索引优点:
索引可以降低服务需要扫描的数据量,减少了IO次数
索引可以帮助服务器避免排序和使用临时表
索引可以帮助将随机I/O转为顺序I/O
50、索引
高性能索引策略:
独立地使用列:尽量避免其参与运算,独立的列指索引列不能是表达式的一部分,也不能是
函数的参数,在where条件中,始终将索引列单独放在比较符号的一侧
例如:select age from students where age-10 < 20;
左前缀索引:构建指定索引字段的左侧的字符数的索引,要通过索引选择性来评估
索引选择性:不重复的索引值和数据表的记录总数的比值;即左侧几个字符已经在表中
能够唯一的被识别
多列索引:AND操作时更适合使用多列索引,而非为每个 列创建单独的索引,即复合索引
选择合适的索引列顺序:无排序和分组时,将选择性最高 放左侧
冗余和重复索引:(A),(A,B)即为冗余索引 不好的索引使用策略,建议扩展索引,而非
冗余;如扩展索引是有A,还想要B,就删除A,新建一个AB索引
51、索引优化建议
只要列中含有NULL值,就最好不要在此例设置索引,复合索 引如果有NULL值,此列在使用时也不会使用索引
尽量使用短索引,如果可以,应该制定一个前缀长度
对于经常在where子句使用的列,最好设置索引
对于有多个列where或者order by子句,应该建立复合索引
对于like语句,以%或者‘-’开头的不会使用索引,以%结尾 会使用索引
尽量不要在列上进行运算(函数操作和表达式操作)
尽量不要使用not in和<>操作
例如:explain select name,age from students where age<>20\G; 不等于20岁的
52、EXPLAIN
通过EXPLAIN来分析索引的有效性:
EXPLAIN SELECT clause
获取查询执行计划信息,用来查看查询优化器如何执行查询
例子:explain select name,age from students where age=20\G;
输出信息说明:
参考 https://dev.mysql.com/doc/refman/5.7/en/explain-output.html
id: 当前查询语句中,每个SELECT语句的编号
复杂类型的查询有三种:
简单子查询
用于FROM中的子查询
联合查询:UNION
注意:UNION查询的分析结果会出现一个额外匿名临时表
例如:select name,age from students union select name,age from teachers;
explain select name,age from students union select name,age from teachers;
常用命令:
create index index_age on students(age); 创建索引
show indexes from students\G; 显示表上的所有索引
explain select name,age from students where age=20\G; 查看执行命令中用到的索引
explain select name,age from students where age > 20\G; 不能使用索引
explain select name,age from students where age > 30\G; ???
explain select name,age from students where age between 20 and 30\G; 不能使用索引
create index index_name on students(name);
explain select from students where name like 's%'\G; 可以使用索引
explain select from students where name like '%g'\G; 不能使用索引
drop index index_name on students; 删除索引
create index index_name_age on students(name,age); 创建复合索引
explain select from students where name like 'w%'\G; 可以使用第一个索引
explain select from students where age=20\G; 跨过第一个索引使用第二个是不行的
explain select from students where name like 'w%' and age=20\G; 第一个索引使用了,
第二个没有使用;
explain select from students where name='wang' and age=20\G; 第一和第二索引都使
用上了;
explain select name,class from students as s inner join classes as c on
s.classid=c.classid\G; 内连接查询有两行,id号同一个
explain select * from students where age > (select age from students where stuid=1)\G;
有子查询,那么id号有两个,查询有两行
53、EXPLAIN
select_type: 查询类型
简单查询为SIMPLE
复杂查询:
SUBQUERY: 简单子查询
PRIMARY:最外面的SELECT
DERIVED: 用于FROM中的子查询 派生查询(语句生成的)
例子:explain select from (select from students where gender='M') as a\G; 可以看到
select的类型,如果看不到就要将变量设为off;先用show variables like '%optimizer%';进行查
询,然后 set optimizer_switch='derived_merge=off';进行设置,之后在查看就可以了;
UNION:UNION语句的第一个之后的SELECT语句
UNION RESULT: 匿名临时表
table:SELECT语句关联到的表
54、EXPLAIN
type:关联类型或访问类型,即MySQL决定的如何去查询表 中的行的方式,以下顺序,性能从低到高
ALL: 全表扫描
index:根据索引的次序进行全表扫描;如果在Extra列出现 “Using index”表示了使用覆盖索
引,而非全表扫描
range:有范围限制的根据索引实现范围扫描;扫描位置始于索 引中的某一点,结束于另一
点
ref: 根据索引返回表中匹配某单个值的所有行
例子:explain select * from students where name= 'wang'\G;
eq_ref:仅返回一个行,但与需要额外与某个参考值做比较
const, system: 直接返回单个行 ;精确匹配
possible_keys:查询可能会用到的索引
key: 查询中使用到的索引
key_len: 在索引使用的字节数
55、EXPLAIN
ref: 在利用key字段所表示的索引完成查询时所用的列或某常 量值
rows:MySQL估计为找所有的目标行而需要读取的行数
Extra:额外信息
Using index:MySQL将会使用覆盖索引,以避免访问表
Using where:MySQL服务器将在存储引擎检索后,再进行 一次过滤
Using temporary:MySQL对结果排序时会使用临时表
Using filesort:对结果使用一个外部索引排序
注意:set global userstat=1;设置索引使用状态,然后用show index_statistics;可以查看哪个索引被使用的情况;要索引查询过后才有东西
56、管理索引
创建索引:
CREATE INDEX index_name ON tbl_name (index_col_name,...);
help CREATE INDEX
删除索引:
DROP INDEX index_name ON tbl_name;
查看索引:
SHOW INDEXES FROM [db_name.]tbl_name;
优化表空间:
OPTIMIZE TABLE tb_name 在表进行了大量的修改操作后执行命令进行磁盘的整理
57、SQL语句性能优化
查询时,能不要就不用,尽量写全字段名
大部分情况连接效率远大于子查询
多表连接时,尽量小表驱动大表,即小表 join 大表
在千万级分页时使用limit
对于经常使用的查询,可以开启缓存
多使用explain和profile分析查询语句
查看慢查询日志,找出执行时间长的sql语句优化
58、并发控制
锁粒度:
表级锁 用户连接过来修改数据时锁住整个表防止其它用户也要修改而产生冲突
行级锁 锁住的是一行
锁:
读锁:共享锁,只读不可写,多个读互不阻塞,
写锁:独占锁,排它锁,一个写锁会阻塞其它读和写锁
实现
存储引擎:自行实现其锁策略和锁粒度
服务器级:实现了锁,表级锁;用户可显式请求 ;自己加是用来解决MyISAM的隔离问题的
分类:
隐式锁:由存储引擎自动施加锁
显式锁:用户手动请求
59、并发控制
锁策略:在锁粒度及数据安全性寻求的平衡机制
显示使用锁
LOCK TABLES
tbl_name [[AS] alias] lock_type
[, tbl_name [[AS] alias] lock_type] ...
lock_type: READ , WRITE
UNLOCK TABLES 解锁
FLUSH TABLES tb_name[,...] [WITH READ LOCK]
关闭正在打开的表(清除查询缓存),通常在备份前加全局读锁;可用于紧急写磁盘;
但是当还有正在读数据的操作时就不能立马刷新,要等待读完才能刷新;可整个系统加锁
SELECT clause [FOR UPDATE | LOCK IN SHARE MODE]
查询时加写或读锁
常用命令:
lock tables students read; 给表加读锁
update students set name='www' where stuid=28; 加了读锁后自己不能写;其它人写
时会被阻塞;
unlock tables; 解锁
lock tables students write; 加写锁;自己读写都可,别人读写都不能
flush tables with read lock; 整个系统全部加锁,而不是某一个数据库
60、事务
事务Transactions:一组原子性的SQL语句,或一个独立工 作单元
事务日志:记录事务信息,实现undo,redo等故障恢复功能
ACID特性:
A:atomicity原子性;整个事务中的所有操作要么全部成 功执行,要么全部失败后回滚
C:consistency一致性;数据库总是从一个一致性状态转 换为另一个一致性状态
I:Isolation隔离性;一个事务所做出的操作在提交之前, 是不能为其它事务所见;隔离有多
种隔离级别,实现并发
D:durability持久性;一旦事务提交,其所做的修改会永 久保存于数据库中
注意:事务日志是存放在/var/lib/mysql下的ib_logfile0和ib_logfile1文件中的;而数据是存放在相应数据库下的,如/var/lib/mysql/hellodb2下的students.ibd;建议数据和日志分开存放;事务的工作示例:第一个事务1、2、3事件都完成,日志已经在每完成一个事件后写完,但数据还没有写到磁盘;继续第二个事务1、2完,3还没做;这时突然系统崩溃;那么在重新启动系统时日志和磁盘数据进行比对,然后第一个事务redo,第二个事务undo;重启慢有这方面重做事务的原因;
61、Transaction生命周期
注意:事务是不记录表的查询操作的,因为没有更改;
62、事务
启动事务:START TRANSACTION
结束事务:
(1) COMMIT:提交 oracle是敲命令进行提交
(2) ROLLBACK: 回滚
注意:只有事务型存储引擎方能支持此类操作
建议:显式请求和提交事务,而不要使用“自动提交”功能
set autocommit={1|0}
事务支持保存点:savepoint 加标签,rollback可以还原到指定点
SAVEPOINT identifier
ROLLBACK [WORK] TO [SAVEPOINT] identifier
RELEASE SAVEPOINT identifier
例子:
insert students(name,age,gender) values('a',20,'M');
insert students(name,age,gender) values('b',30,'M');
select from students;
savepoint ab;
insert students(name,age,gender) values('c',23,'F');
insert students(name,age,gender) values('d',30,'F');
savepoint cd;
insert students(name,age,gender) values('e',38,'F');
select from students;
rollback to cd;
select from students;
rollback to cd;
rollback to ab;
rollback;
常用命令:
set autocommit=0
update students set name='www' where stuid=28;
select from students;
commit;
注意:由于事务的隔离级别的限制,当一个用户修改数据库的数据时,另一个用户读取到的
是原来的数据,而不是正在修改的新数据;