1、MYSQL高级概述
【1】架构概述 【2】索引优化 【3】查询截取 【4】mysql锁机制 【5】主从复制
2、MYSQL概述
【1】mysql内核 【2】sql优化工程师 【3】mysql服务器的优化 【4】各种参数常量设定 【5】查询语句优化 【6】主从复制 【7】软硬件升级 【8】容灾百分 【9】sql编程
3、MYSQL Linux版的安装
【1】到Linux章节查看具体的安装步骤 【2】查看mysql是否安装 rpm -qa|grep -i mysql 【3】mysqladmin --version 查看mysql版本 【4】service mysql start 【5】service mysql stop 【6】ps -ef|grep mysql 查看后台服务 【7】chkconfig mysql on 设置开机自启动 【8】chkconfig --list | grep mysql
5、MYSQL的安装位置
【1】建立的库在机器上都能看的到。/var/lib/mysql 这个就是存放位置 【2】/usr/share/mysql 【3】/usr/bin 【4】/etc/init.d/mysqld
6、修改字符集
【1】修改默认的配置文件/usr/share/mysql —> my-default.cnf 【2】具体修改参数 [client] default-character-set=utf8 [mysql] default-character-set=utf8 [mysqld] init_connect='SET collation_connection = utf8_unicode_ci' init_connect='SET NAMES utf8' character-set-server=utf8 collation-server=utf8_unicode_ci skip-character-set-client-handshake skip-name-resolve 【3】重启mysql 重新建立库 【4】查看编码show variables like '%char%';
7、MySQL高级配置文件
【1】二进制日志log-bin 主从复制 【2】错误日志log-error 默认关闭 【3】查询日志log 【4】数据文件 rfm 表结构 ; myd 存放博爱数据 ; myi 存放表索引 【5】如何配置
8、MYSQL逻辑架构
【1】Connection Pool 连接池 【2】Interface Parser Optimizer Caches&Buffers 【3】Pluggable Storage Enginess 可拔插存储引擎 【4】文件存储层 File system Files & Logs 【5】MYSQL与众不同,它的架构可以在多种不同的场景中应用并发挥良好作用。插件式处处引擎架构查询处理和数据存储 提取相分离。 【6】连接层、服务层、引擎层、存储层—>四层结构
9、存储引擎概述
【1】show engines; 【2】show variables like '%storage_engine%'; 【3】MyISAM和InnoDB 阿里巴巴、淘宝用的哪个
10、SQL性能下降原因
【1】性能下降:执行时间长、等待时间长 【2】索引:select * from user where name='' and email=''; create index idx_user_name on user(name); # 建立索引 create index idx_user_nameEmail on user(name,email);# 多重索引 【3】关联查询太多join(设计缺陷或不得已的需求) 【4】服务器调优及各个参数设置(缓冲、线程数等)
11、SQL执行加载顺序
【1】手写:select distinct from 表 left join 表 on 条件 where group by having order by limit 【2】机读顺序:from on where group by having select distinct order by limit
12、七种JOIN理论
【1】select 表1.id,表2.id from 表1 left join 表2 on 表1.id=表2.id
13、七种JOIN的SQL编写
【1】建立部门表 create table department( id int(11) not null auto_increment, name varchar(30) default null, ioc_add varchar(40) default null, primary key(id) )engine=innodb auto_increment=1 default charset=utf8; 【2】建立员工表 create table employee( id int(11) not null auto_increment, name varchar(20) default null, department_id int(11) default null, primary key(id), key fk_department_id(department_id) )engine=innodb auto_increment=1 default charset=utf8; 【3】插入部门数据 insert into department(department.name,department.ioc_add) values('RD',11); insert into department(department.name,department.ioc_add) values('HR',12); insert into department(department.name,department.ioc_add) values('MK',13); insert into department(department.name,department.ioc_add) values('MIS',14); insert into department(department.name,department.ioc_add) values('FD',15); 【4】插入员工数据 insert into employee(employee.name,employee.department_id) values('z3',1); insert into employee(employee.name,employee.department_id) values('z4',1); insert into employee(employee.name,employee.department_id) values('z5',1); insert into employee(employee.name,employee.department_id) values('w5',2); insert into employee(employee.name,employee.department_id) values('w6',2); 【5】笛卡尔集 select * from department; select * from employee; select * from department,employee; # 前两个乘积 25 【6】inner join select * from employee inner join department on employee.department_id=department.id 【7】left join select * from employee left join department on employee.department_id=department.id 【8】right join select * from employee right join department on employee.department_id=department.id 【9】增加where条件 select * from employee right join department on employee.department_id=department.id where department.id=null 【10】union 合并加去重 select * from employee left join department on employee.department_id=department.id union select * from employee right join department on employee.department_id=department.id
14、索引的概述
【1】Index,是帮助MySQL高效获取数据的数据结构。本质:索引是数据结构 【2】索引的目的在于提高查询效率,可以类比字典 【3】可以理解为排好序的快速查找数据结构 【4】在数据之外,数据库系统还维护着满足特定查找算法的数据结构 【5】折中比大小的思路,二叉树查找 【6】尽量使用逻辑删除,而不是使用逻辑删除 【7】索引本身也很大,所以不可能全部存在内存,因此往往以索引文件的形式存储在磁盘上 【8】我们所说的索引,如果没有特别指明,都是指B树(多路搜索树)结构组织的索引。
15、索引的优缺点
【1】优点:提升数据索引效率,降低数据的IO成本。通过索引排序,降低排序成本,降低了CPU消耗 【2】缺点:索引也是需要占空间的。(1)提升了查询表速度,但是降低了更新表的速度(2)需要花时间研究优秀的索引字段
16、索引分类与索引建立语句
【1】单值索引:一个索引只包含单个列,一个表可以有多个单列索引 【2】唯一索引:索引值必须唯一,单允许空值 【3】符合索引:即一个索引包含了多个列 【4】语法 (1)create [unique] index indexName on my_table(column_name(length));// 建立1 (2)alter my_table add [unique] index [indexName] on (column_name(length)); //建立2 (3)drop index [indexName] on my_table; (4)show index from table_name 例如show index from department; (5)四种方式添加数据表的索引: alter table table_name add primary key(column_list); 添加一个主键,意味着索引值必须是唯一的,且不为null alter table table_name unique index_name(column_list);索引值必须唯一,null除外 alter table table_name add index index_name(column_list); 普通索引,索引值可出现多次 alter table table_name add fulltext index_name(column_list);改语句指定了索引为fulltext,用于全文索引
18、建立索引情况概述
【1】主键自动建立唯一索引 【2】频繁作为查询条件的字段应该创建索引 【3】查询汇总与其他表关联的字段,外键关系建立索引 【4】频繁更新的字段,不适合创建索引 【5】where条件里用不到的字段不创建索引 【6】单键/组合索引的选择问题?who?(在高并发倾向创建组合索引) 【7】查询中排序的字段,排序字段若通过索引去访问将大大提高排序速度 【8】查询中统计或分组字段
19、不建立索引情况概述
【1】表记录太少不建 【2】经常增删改的表不建 【3】如果某个数据列包含许多重复的内容,不建索引
20、性能分析
【1】MySQL查询优化分析器。他认为最优的,不见得是DBA认为是最优的 【2】MySQL常见瓶颈:CPU、IO、服务器硬件的性能瓶颈 【3】explain
21、Explain概述
【1】就是查看执行计划 【2】explain + 您的sql语句 【3】读取顺序、操作类型、哪些索引可以使用、哪些索引实际被使用、表之间的引用、每张表有多少行被优化器查询
22、Explain之id概述
【1】id相同,执行顺序由上而下 【2】id不同,id值越大,越先被执行
23、Explain之select_type与table概述
【1】select_type 查询类型 (1)simple 简单的select查询 (2)primary (3)subquery (4)derived 临时表 (5)union 联合查询 (6)union result 两种union结果的合并 【2】table 就是数据关联那张表
24、Explain之type概述
【1】从最好到最差依次是system->const—>eq_ref—>ref—>range—>index—>ALL 【2】能达到range级别,最好达到ref级别 【3】system 表只有一行记录,平时基本不会出现,可以忽略不计 【4】const 表示通过索引一次就找到了。只匹配一行数据 explain select * from (select * from employee where employee.id=1) as e; 【5】eq_ref,唯一性索引扫描,表中只有一条记录与之匹配。 explain select * from department,employee where employee.id=department.id; 【6】ref 返回匹配某个单独值的所有行,需要配合着使用的。 alter table department add index idx_col(name,ioc_add); --------------------------------------------------------- explain select * from department where department.name='RD' //这里的区别是非唯一性、就达到ref级别了 【7】range explain select * from employee where id BETWEEN 1 and 20 ----------------------------------- explain select * from employee where id in (1,2,6) 【8】index 全索引扫描 explain select id from employee 【9】ALL explain select * from employee
25、Explain之possible_keys与key概述
【1】到range和ref就很好了(百万数据以上) 【2】possible_keys预估可能用到的索引 【3】key是实际用到的索引 EXPLAIN select * from employee left join department on employee.department_id=department.id union select * from employee right join department on employee.department_id=department.id ---------------------------------------- EXPLAIN select department.name,department.ioc_add from department 【4】覆盖索引:就是select 字段.... 刚好和索引列一致。 EXPLAIN select department.name,department.ioc_add # 这两个字段刚好在前面建立了一个索引 from department
26、Explain之key_len概述
【1】key_len表示索引中使用的字节数,在不损失精确性的情况下,长度越短越好 【2】key_len显示值为索引子弹的最大可能长度,并非实际长度。即key_len是根据表定义计算而得,不是通过表内检索出的
27、Explain之ref概述
【1】显示索引的那一列被使用了,如果可能的话,是一个常数。哪些列或常量被用于查找索引列上的值
28、Explain之rows概述
【1】表的读取顺序 【2】rows 根据表统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数 EXPLAIN select * from department,employee where department.id=employee.id and department.ioc_add='11'
29、Explain之Extra
【1】包含不适合在其他列中显示但十分重要的额外信息 【2】Using where; Using index 用了条件、用了索引 Using where; Using index; Using temporary; Using filesort -------------------------------------------------------- EXPLAIN select * from department,employee where department.id=employee.id and department.ioc_add='11' order by employee.id 【3】而Using filesort是不好的,如果可以尽快优化 【4】Using temporary这个更难受、产生了内部的临时表;order by group by往往会产生,会拖慢SQL 【5】所以order by、group by的字段,一定要建立索引,这样才能提高速度 【6】Using index比较牛批了,表示响应的操作使用了覆盖索引,避免访问了表的数据行,效率不错。 (1)如果同时出现Using where 表名索引被用来执行索引键值的查找; (2)如果没有出现Using where,表明索引用来读取数据而非执行查找动作; 【7】实际案例 (1)create index idx_user_nameEmail on user(name,email); (2)explain select email from user where user.email='cx@163.com' (3)explain select name,email from user 【8】覆盖索引Covering index select 数据列只从索引中就能够取得,不必读取数据行 【9】Using where 条件 【10】Using join buffer 使用了连接缓存 【11】impossible where : where的值总是false where a=1 and a=2 【12】select tables optimized away 在没有group by字句的情况下,基于索引优化操作或存储引擎优化 【13】distinct 找到第一个匹配后就不找了。
31、单表优化案例
【1】设计表 SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0;-- ---------------------------- -- Table structure for article -- ---------------------------- DROP TABLE IF EXISTS `article`; CREATE TABLE `article` (`id` int(6) NOT NULL AUTO_INCREMENT,`author_id` int(6) NULL DEFAULT NULL,`category_id` int(6) NULL DEFAULT NULL,`views` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,`comments` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,`title` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,`content` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Compact;-- ---------------------------- -- Records of article -- ---------------------------- INSERT INTO `article` VALUES (1, 1, 1, '1', '1', '1', '1'); INSERT INTO `article` VALUES (2, 2, 2, '2', '2', '2', '2'); INSERT INTO `article` VALUES (3, 1, 1, '3', '3', '3', '3');SET FOREIGN_KEY_CHECKS = 1; 【2】SQL select article.id,article.author_id from article where article.category_id=1 and article.comments > 1 order by article.views desc LIMIT 1 【3】详解 EXPLAIN select article.id,article.author_id from article where article.category_id=1 and article.comments > 1 order by article.views desc LIMIT 1 【4】查看索引情况 show index from article 【5】新建索引,发现在type上与优化了 create index idx_article_ccv on article(category_id,comments,views) ---------- EXPLAIN select article.id,article.author_id from article where article.category_id=1 and article.comments > 1 order by article.views desc LIMIT 1 【6】因为有个范围索引不太合适,所以用重新建立索引,再次查询可以了,Extra也优化了,牛批 drop index idx_article_ccv on article -------------------- create index idx_article_cv on article(category_id,views) -------------------- EXPLAIN select article.id,article.author_id from article where article.category_id=1 and article.comments > 1 order by article.views desc LIMIT 1
32、两个表优化案例
【1】建立两个表 (1) SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0;-- ---------------------------- -- Table structure for book -- ---------------------------- DROP TABLE IF EXISTS `book`; CREATE TABLE `book` (`id` int(6) NOT NULL AUTO_INCREMENT,`card` int(6) NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Compact;-- ---------------------------- -- Records of book -- ---------------------------- INSERT INTO `book` VALUES (1, 20); INSERT INTO `book` VALUES (2, 13); INSERT INTO `book` VALUES (3, 7);SET FOREIGN_KEY_CHECKS = 1; (2) SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0;-- ---------------------------- -- Table structure for class -- ---------------------------- DROP TABLE IF EXISTS `class`; CREATE TABLE `class` (`id` int(20) NOT NULL AUTO_INCREMENT,`card` int(20) NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 21 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Compact;-- ---------------------------- -- Records of class -- ---------------------------- INSERT INTO `class` VALUES (1, 10); INSERT INTO `class` VALUES (2, 7); INSERT INTO `class` VALUES (3, 3); INSERT INTO `class` VALUES (4, 13); INSERT INTO `class` VALUES (5, 17); INSERT INTO `class` VALUES (6, 4); INSERT INTO `class` VALUES (7, 9); INSERT INTO `class` VALUES (8, 13); INSERT INTO `class` VALUES (9, 16); INSERT INTO `class` VALUES (10, 16); INSERT INTO `class` VALUES (11, 20); INSERT INTO `class` VALUES (12, 13); INSERT INTO `class` VALUES (13, 3); INSERT INTO `class` VALUES (14, 15); INSERT INTO `class` VALUES (15, 5); INSERT INTO `class` VALUES (16, 20); INSERT INTO `class` VALUES (17, 6); INSERT INTO `class` VALUES (18, 9); INSERT INTO `class` VALUES (19, 6); INSERT INTO `class` VALUES (20, 4);SET FOREIGN_KEY_CHECKS = 1; 【2】查看SQL性能 EXPLAIN select * from class left join book on class.card=book.card where book.id is not null 【3】添加索引 alter table book add index Y (card) ------- alter table class add index Z (card) --------- EXPLAIN select * from class left join book on class.card=book.card where book.id is not null 【4】如果删除你再看下性能 drop index Y on book; 【5】结论:左连接就加载右表即可(反向加) 【6】如果发现DBA建的顺序和预期不符,连接查询的时候换一下位置
33、索引三表优化案例
【1】show index from class 【2】drop index Z on class 【3】查看和清除表的索引 show index from book drop index Y on book 【4】三表连接查询 EXPLAIN select * from class left join book on class.card=book.card left join phone on book.card=phone.card where book.card is not null and phone.card is not null 【5】建立索引 alter table book add index A (card) ------- alter table class add index B (card) -------- alter table phone add index C (card) -------- EXPLAIN select * from class left join book on class.card=book.card left join phone on book.card=phone.card where book.card is not null and phone.card is not null 【6】结论:索引最好设置在经常查询的字段中。 (1)尽量减少join语句中的循环总次数 (2)永远用小结果集驱动大的结果集 (3)如果无法保证驱动表join条件字段被索引,如果内存充足,可以把joinBuffer设置大点
34、索引优化
【1】索引失效(应该避免) 【2】建立数据库表 SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0;-- ---------------------------- -- Table structure for staffs -- ---------------------------- DROP TABLE IF EXISTS `staffs`; CREATE TABLE `staffs` (`id` int(6) NOT NULL AUTO_INCREMENT,`name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,`age` int(6) NOT NULL DEFAULT 0,`position` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,`time` datetime NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (`id`) USING BTREE,INDEX `idx_staffs_name_age_position`(`name`, `age`, `position`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Compact;-- ---------------------------- -- Records of staffs -- ---------------------------- INSERT INTO `staffs` VALUES (1, '陈翔', 20, '经理', '2022-06-19 21:28:37'); INSERT INTO `staffs` VALUES (2, '蘑菇头', 19, '演员', '2022-06-19 21:28:56'); INSERT INTO `staffs` VALUES (3, '润土', 24, '主管', '2022-06-19 21:29:12');SET FOREIGN_KEY_CHECKS = 1; 【3】建立索引 alter table staffs add index idx_staffs_name_age_position(name,age,position) 【4】索引失效的原因总结 (1)全值匹配我最爱 EXPLAIN select * from staffs where staffs.name='陈翔' --------- EXPLAIN select * from staffs where staffs.name='陈翔' and age=20 ------------- EXPLAIN select * from staffs where staffs.name='陈翔' and staffs.age=20 and staffs.position='经理' --------------- 【5】索引失效了 EXPLAIN select * from staffs where staffs.age=19 and staffs.position='演员' ------------- EXPLAIN select * from staffs where staffs.position='演员' 【6】结论:alter table staffs add index idx_staffs_name_age_position(name,age,position) (1)最佳左前缀法则,如果索引了多列,查询要从索引最左列开始,并且不能跳过索引列 (2)----就是带头大哥不能死。----死了索引就失效 (3)----中间兄弟不能断。-------(断了就是使用了部分索引,只能使用到断之前的索引了)
35、索引优化-二
【1】不在索引列上做任操作(计算、函数、类型转换),会导致索引失效而转向全表扫描 EXPLAIN select * from staffs where staffs.name='陈翔' ---------------------- 失效的情况: EXPLAIN select * from staffs where left(staffs.name,1)='陈' 【2】结论:索引内容少计算
36、引擎优化-三
【1】常量查询 EXPLAIN select * from staffs where staffs.name='陈翔' and staffs.age=20 and staffs.position='经理' 【2】不能使用索引的范围判断,不然后面的索引就失效了 EXPLAIN select * from staffs where staffs.name='陈翔' and staffs.age>19 and staffs.position='经理'
37、索引优化-四
【1】尽量使用覆盖索引,减少使用select *;下面的语句就比36的多用了Using index EXPLAIN select staffs.`name`,staffs.age,staffs.position from staffs where staffs.name='陈翔' and staffs.age=20 and staffs.position='经理' 【2】原则:谁建立了索引,尽量就查谁
38、索引优化-五
【1】MYSQL不用使用!=或者<>,使用了会导致索引失效 【2】但是如果确实用到,也可以写
39、索引优化-六
【1】如果对非空字段进行空判断 EXPLAIN select * from staffs where name is null
40、索引优化-七
【1】两边有百分号,索引就失效了 EXPLAIN select * from staffs where name like '%陈翔%' 【2】但是如果只使用右边%,索引还是起作用的 EXPLAIN select * from staffs where name like '陈翔%' 【3】如果必须两边都用%%号,则使用覆盖索引(建的索引和查的字段、顺序、数量完全一致) create index idx_user_name_age on user(name,age) ------------------- EXPLAIN select user.name from user where user.name like '陈翔%'
41、索引优化-八
【1】varchar不加单引号导致索引失效,这个是开发中的重罪 EXPLAIN select * from staffs where staffs.name='陈翔' ----------------------- EXPLAIN select * from staffs where staffs.name=2000 # mysql 会使用隐式的类型转换 【2】少用or
44、索引面试题分析
【1】复合索引 create index idx_user_c1_c2_c3_c4 on user(c1,c2,c3,c4) 【2】全值匹配我最爱 【3】建立的是1、2、3、4,用的时候是4、3、2、1 ,索引仍不会失效,这是因为mysql聪明 【4】但是我们推荐的还是怎么建立,怎么使用索引 【5】范围之后的索引会全部失效,但是如果范围是最高的楼那就无所谓了 【6】Using filesort 九死一生
46、查询截取详解-小表驱动大表
【1】Explain 分析 【2】观察,至少跑1天,看看生产慢SQL情况。 【3】开启慢查询日志,是指阈值,超过5S的SQL都抓取出来 【4】Explain+慢SQL分析 【5】show profile:查询mysql服务器里的执行细节和声明周期情况 【6】运维经理 OR DBA,进行SQL数据库服务器的参数调优 【7】永远用“小表驱动大表” 【8】当B表数据小于A表的数据集时,用in优于exists select * from A where id in(select id from b) 【9】当A表数据集小于B表,用exists优于in 【10】将主查询的数据,放到子查询中做条件验证,根据验证结果(True或False)来决定查询的结数据结果是否保留
47、in与exists
【1】查询用in select * from staffs where staffs.id in (select book.id from book) ------------ select * from staffs where staffs.id in (select 1 from book) --------------- 【2】查询用exists select * from staffs where EXISTS (select book.id from book where book.id=staffs.id)
48、排序使用索引order by优化
【1】会不会产生filesort 【2】show index from staffs 让age成为带头大哥 【3】drop index idx_staffs_name_age_position on staffs 【4】create index idx_staffs_age_postion on staffs(age,position) 【5】带头大哥查询、排序,不会使用filesort EXPLAIN select staffs.age from staffs where staffs.age>20 order by staffs.age 【6】会使用filesort,效果差 EXPLAIN select staffs.age from staffs where staffs.age>20 order by staffs.position 【7】不会使用filesort,尽量使用Index方式排序 EXPLAIN select staffs.age,staffs.position from staffs where staffs.age>20 order by staffs.age,staffs.position 【8】order by (1)语句使用索引最做前列 (2)使用Where字句与Order by字句提哦啊见组合满足索引最左前列 【9】双路排序与单路排序 (1)MySQL4.1之前使用的是双路排序,扫描两次磁盘,最终得到数据 (2)在MySQL4.1之后,推出了单路排序 (3)由于单路是后出的,总体来说是好过双路的。但是用单路有问题,一次抓不完,性能反而不如双路。 【10】优化策略 (1)增大sort_buffer_size参数的设置 (2)增大max_length_for_sort_data参数的设置 (3)只要有order by就不用select * 【11】小结: (1)尽量不要用* (2)增加sort_buffer_size与max_length_for_sort_data长度 (3)扫描有序索引排序、mysql能为查询与排序使用相同的索引 (4)如果order by是常量,则可以排序,反正不产生filesort就对了 (5)跳楼机不要用、带头大哥不能死、中间兄弟不能断
49、慢日志查询
【1】group by实质是先排序后分组 【2】能用where搞定的,就不要写having 【3】慢查询日志,是MySQL提供的一种日志,超过long_query_time值的SQL,会被记录到日志中 【4】show VARIABLES like '%slow_query_log%' 查询是否开启 【5】开启与其他操作 (1)set global slow_query_log=1; # mysql重启后会失效,一般用不到永久的 (2)查询定义慢查询的时间show VARIABLES like '%long_query_time%' (3)set global long_query_time=3 修改后需要重新打开sql链接 (4)select sleep(4) (5)cd /var/lib/mysql 有主机名-slow.log 【6】mysqldumpslow 查询执行慢的sql (1)mysqldumpslow --help (2)得到返回记录最多的10个sql mysqldumpslow -s r -t 10 /var/lib/mysql/xxx-slow.log (3)得到访问次数最多的10个sql mysqldumpslow -s c -t 10 /var/lib/mysql/xxx-slow.log (4)得到按时间排序的前10条里面含有左连接的查询语句 mysqldumpslow -s t -t 10 -g “left join”/var/lib/mysql/xxx-slow.log (5)另外在使用只写命令时,建议加上 | more mysqldumpslow -s r -t 10 /var/lib/mysql/xxx-slow.log | more
50、批量插入数据脚本
【1】mysql写函数 【2】新建库 create database bigData; use bigData 【3】创建表 create table department( id int UNSIGNED PRIMARY key auto_increment, no MEDIUMINT UNSIGNED not null DEFAULT 0, name varchar(20) not null DEFAULT "", ico varchar(20) not null DEFAULT "" )ENGINE=INNODB DEFAULT CHARSET=GBK; ---------------------------------- create table employee( id int UNSIGNED PRIMARY key auto_increment, no MEDIUMINT UNSIGNED not null DEFAULT 0, name varchar(20) not null DEFAULT "", job varchar(20) not null DEFAULT "", manage_no MEDIUMINT UNSIGNED not null DEFAULT 0, hiredate date not null, salary DECIMAL(7,2) not null, package DECIMAL(7,2) not null, department_no MEDIUMINT UNSIGNED not null DEFAULT 0 )ENGINE=INNODB DEFAULT CHARSET=GBK; 【4】创建函数如果报错this function has none of deterministic... show variables like 'log_bin_trust_function_creators' --------- set global log_bin_trust_function_creators=1; 也是临时的设置,但是临时设置也足够了 【5】随机产生字符串的函数 DELIMITER $$ create function rand_string(n int) returns varchar(255) beginDECLARE chars_str varchar(100) DEFAULT 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';DECLARE return_str varchar(255) DEFAULT '';DECLARE i int DEFAULT 0;while i < n DOset return_str=concat(return_str,substring(chars_str,floor(1+rand()*52),1));set i= i+1;end while;return return_str; end $$ 【6】随机产生部门编号 DELIMITER $$ create function rand_num() returns int(5) beginDECLARE i int DEFAULT 0;set i=floor(100+rand()*10); return i; end $$ 【7】创建存储过程 DELIMITER $$ create procedure insert_employee(in start int(10),in max_num int(10)) begin DECLARE i int DEFAULT 0;set autocommit=0;repeatset i=i+1;insert into employee(employee.`no`,employee.name,employee.job,employee.manage_no,employee.hiredate,employee.salary,employee.package,employee.department_no) values ((start+i),rand_string(6),'salesman',0001,CURDATE(),2000,400,rand_num());until i=max_numend repeat;COMMIT;end $$ ----------- DELIMITER $$ create procedure insert_department(in start int(10),in max_num int(10)) begin DECLARE i int DEFAULT 0;set autocommit=0;repeatset i=i+1;insert into department(department.`no`,department.name,department.ico) values ((start+i),rand_string(10),rand_string(8));until i=max_numend repeat;COMMIT;end $$ ------- drop procedure insert_department 这是删除的方法 【8】调用存储过程 select * from department; ----------------- delimiter; call insert_department(100,10); --------------- 插入50万 delimiter; call insert_department(1000000,500000);
51、用show profile进行sql分析
【1】查询优化-慢查询日志-批量数据脚本-show profile-全局日志查询 【2】mysql提供可以用来分析当前会话中语句执行的资源消耗情况,可以用于SQL调优测量 【3】默认情况下默认是关闭的,并保存最近15此的运行结果 【4】show VARIABLES like 'profiling' (1)set profiling=on (2)show VARIABLES like 'profiling' 【5】show profiles; (1)show profile cpu,block io for query 3 #找个耗时比较久的查看替换3 (2)执行后可以看到每一步的执行耗时; (3)converting heap to MyISAM 查询结果太大,内存不够,开始用磁盘了 (4)creating temp table 创建了临时表 (5)Copying to temp table on disk 把内存中的临时表复制到磁盘,非常危险!!! (6)locked 死锁
52、全局查询日志
【1】只能在测试环境使用 【2】开启查询 (1)set global general_log=1; (2)set global log_output='TABLE'; (3)此后所写的SQL将会记录到mysql库里的general_log表 (4)select * from mysql.general_log;
53、数据库锁理论概述
【1】锁是计算机协调多个进程或线程并发访问某一资源的机制 【2】商品只有一件,谁能购买到,需要用到锁的隔离和并发的矛盾 【3】锁的分类 (1)从对数据操作的类型分:读锁(共享)、写锁(排他) (2)从对数据操作的粒度分,分为表锁和行锁
54、读锁案例讲解
【1】表锁、行锁 【2】建立表演示 create table mylock( id int not null primary key auto_increment, name varchar(20) )engine myisam; --------------- insert into mylock(name) values('a'); insert into mylock(name) values('b'); insert into mylock(name) values('c'); insert into mylock(name) values('d'); insert into mylock(name) values('e'); 【3】锁表 (1)show open tables #查看表的锁情况 In_use 为0 代表没有锁 ------------ show open tables from study; (2)lock table mylock read,book write; mylook book的In_use都是1 带包加锁 (3)unlock tables; 【4】加锁后lock table mylock read; (1)select * from mylock; session 1可以读 (2)update mylock set mylock.name='a2' where id=1; session 1不能修改 (3)session 1不能读别的表,因为锁着在 select * from book; (4)但是另个一连接session 2,可以查锁,也可以查别的表 (5)session 2如果修改session 1的表,则需要等待,只有session 1执行unlock tables;才能修改
55、锁的案例讲解
【1】lock table mylock write; ---------------------------------- 【2】读写情况 (1)select * from mylock; 可读 (2)update mylock set mylock.name='a3' where mylock.id=1;可写 (3)但是锁着,不update的话,select * from book;会报错Table 'book' was not locked with LOCK TABLES (4)session2 被阻塞,需要等待锁被释放 ---------------------------------- 【3】查看被加锁的表 show open tables; 有1的就是锁着的 ---------------------------------- 【4】myisam要偏读,不要偏写。
56、行锁理论
【1】行锁粒度最小,发生锁冲突的概率最低,并发度也最高。 【2】innodb与myisam的最大不同点:一是事务支持,而是采用了行级锁 【3】行锁支持事务 (1)事务的ACID属性:原子性、一致性、隔离性、持久性 (2)并发事务处理带来的问题:丢失、脏读、不可重复度、幻读 (3)事务隔离级别:未提交度、已提交读、可重复读、可序列化 (4)show VARIABLES like 'tx_isolation'; mysql出厂的时候默认是可重复读
57、行锁案例讲解
【1】数据准备 create table test_innodb_lock( a int(11), b varchar(20) )engine=INNODB 【2】插入数据 insert into test_innodb_lock values(1,"A"); insert into test_innodb_lock values(2,"B"); insert into test_innodb_lock values(3,"C"); insert into test_innodb_lock values(4,"D"); insert into test_innodb_lock values(5,"E"); insert into test_innodb_lock values(6,"F"); 【3】建立两个单值索引 create index test_innodb_lock_a on test_innodb_lock(a); create index test_innodb_lock_b on test_innodb_lock(b); 【4】查询数据 select * from test_innodb_lock; (1)set autocommit=0; 不让自动提交 (2)update test_innodb_lock set b='4001' where test_innodb_lock.a=4; (3)COMMIT
59、索引失效行锁变表锁
【1】varchar必须加单引号,否则是重罪 【2】update test_innodb_lock set a=41 where b=4000; 假如b varchar没加引号 【3】这个session1不写单引号,session2规范执行就回被阻塞 【4】这样就会导致行锁变表锁
60、间隙锁危害
【1】就是session1用范围条件、session2用相等检索 【2】mysql会根据范围错杀,而不会放过,seesion2会阻塞
61、如何锁一行
【1】select xxx for update 锁定某一行后,其他的操作会被阻塞 【2】直到上面的语句执行提交commit,其他的操作才会被执行
62、行锁总结
【1】行锁针对innodb,性能相比myisam有比较明显的优势 【2】也有缺点,当使用不当,innodb会行锁变表锁,性能可能比myisam更差 【3】当前正在等待锁定的数量 show STATUS like 'innodb_row_lock%' 【4】系统启动后到现在总共等待的次数 show STATUS like 'innodb_row_lock_waits%' 【5】页锁,在行锁和表锁之前,会触发死锁,用的相对少很多
63、主从复制
【1】复制的基本原理 (1)slave会从master读取binlog来进行数据同步 (2)主机改变记录到二进制日志—>slave将master日志拷贝到它的中继日志—>slave将自己日志改变到数据库 (3)每一个slave只有个master、每个slave只能有且仅有一个服务器ID (4)每个master可以有多个slave 【2】要求 (1)mysql版本要求一致,且后台已经启动服务 (2)必须同一网段,就是“互相”可以访问 (3)主机修改my.cnf文件 server-id=1、log-bin=/var/.../data/mysqlbin (4)log-err/var/...../data/mysqlerr (5)basedir="mysql的安装路径" (6)tmpdir="/var/.../MySQLServer5.6" (7)datadir="/var/devSoft/data/" (8)read-only=0 (9)binlog-do-db=ww2 【3】从机修改 my.cnf (1)log-bin (2)server-id=2 【4】修改后要重启数据库 (1)grant replication slave on *.* to 'zs'@'从机器数据库IP' indentified by '123456' (2)show master status;查询主机状态 【5】从机的配置 (1)change master to master_host='主机IP',MASTER_USER='zs',MASTER_PASSWORD='123456',MASTER_LOG_FILE='File名字',MASTER_LOG_POS=Position数字; (2)start slave (3)show slave statusG 启动后必须看到Slave_IO_Running Yes、Slave_SQL_Running Yes 【6】最后在主机插入一条数据,从机自动就会复制这条数据,两个数据库都能查的到。 【7】stop slave 停止从机。从机的配置一定要根据show master status主机的状态决定