提升自己,想进入大型互联网公司。欢迎关注我的微信公众号 ,搜索微信公众号:"一起写程序" ,会分享系列文章,希望大家能一起学习。
目录
问题2)索引不是越多越好,而是建立有效的索引,才是好的。... 1
问题3)mysql是基于文件的。不同mysql版本优化器有差别。... 1
问题5)慢查询,日志的内容都是什么?存储格式是什么?... 2
问题7)pt-query-digest /var/run/mysqld/mysqld-slow.log | more生成的报表,结构和内容?... 10
问题9)通过sql的执行计划explain,找到需要优化的点?... 12
问题10)对Count()使用和Max()的优化,通过建立索引?... 16
问题19)数据库三范式,及部分依赖,完全依赖,传递依赖?... 21
问题17)Linux下的Mysql用命令执行sql文件... 28
问题1)数据库优化哪个占比最大?
问题2)索引不是越多越好,而是建立有效的索引,才是好的。
要根据数据库范式设计出数据库表结构,才能进行sql和索引优化,如果没有好的数据库表结构,就没有sql和索引的优化。
问题3)mysql是基于文件的。不同mysql版本优化器有差别。
问题4)哪些sql是要优化的,通过看日志
1, 查看慢查询是否开启,然后开启。
Show variables like ‘slow_query_log’ 查看是否开启慢查询日志。
开启慢查询日志:set global slow_query_log = on
2,设置慢查询日志文件位置和查看慢查询日志文件位置。
设置:Set global Slow_ query_ log_file =慢查日志存储的位置。
查看:mysql> show variables like 'slow%';
3,将没有使用所索引的查询,也记录到日志文件中。
Log_ queries _not _using _indexes
set global log_ queries_ not_ using_ indexes=on;
4, 将超过多少秒的sql记录下来?
Long_ query _time 将超过多少秒的sql记录下来。
5,查看所有变量设置情况,看看是否设置成功了。
Show variables like ‘%log%’
6,查看某一个变量设置情况。
show variables like ‘变量名’
7,设置某个变量?
Set global 变量名=’’
问题5)慢查询,日志的内容都是什么?存储格式是什么?
分成5部分:
sql执行时间:
# Time: 181228 15:09:45
执行sql的主机信息:
# User@Host: root[root] @ localhost [127.0.0.1]
Sql的执行信息: 包括执行所需时间,锁定时间,所发送行数,执行的行数
# Query_time: 0.000986 Lock_time: 0.000000 Rows_sent: 2 Rows_examined: 2
以时间戳的形式记录sql执行时间。
SET timestamp=1545980985;
Sql的内容:
select * from store limit 10;
问题6)sql慢查询日志的分析工具?
工具一:mysqldumpslow
- Myslqdumpslow是安装mysql的时候自动安装的。
- 通过myslqdumpslow –h 查看的帮助。提示信息。
工具二:pt-query-disgest
安装pt-query-digest:
pt-query-digest是一个perl脚本,只需下载并赋权即可执行。pt-query-digest包含在percona-toolkit里面,如果已经安装过percona-toolkit则可以直接使用(percona-toolkit安装方法请参考Linux系统中percona-toolkit的安装方法),下面是centos系统中pt-query-digest的单独安装方法
# yum install perl-DBI
# yum install perl-DBD-MySQL
# yum install perl-Time-HiRes
# yum install perl-IO-Socket-SSL
#快速安装
wget https://www.percona.com/downloads/percona-toolkit/2.2.16/RPM/percona-toolkit-2.2.16-1.noarch.rpm && yum localinstall -y percona-toolkit-2.2.16-1.noarch.rpm
问题7)pt-query-digest查看帮助?
[root@localhost media]# pt-query-digest --help
常用选项: —create-review-table 当使用—review参数,把分析结果输出到表中
—create-history-table 当使用—history参数,把分析结果输出到表中
—filter 对输入的慢查询按指定的字符串进行匹配过滤后,在进行分析
—limit 限制输出结果百分比或数量,默认值是20,即将最慢的20条语句输出
—host HostName
—user 用户名
—password 密码
—history 将分析结果保存到表中,分析结果比较详细
—review 将分析结果保存到表中
—output 分析结果输出类型
—since 从什么时间开始分析,值为字符串
—until 截止时间,配合since一起分析
分析结果:
其中:
Overall:总共有多少条查询
unique:唯一查询数量(不重复的sql)
Time range:查询执行的时间范围
total:总计
min:最小
max:最大
avg:平均
95%:95%的查询时间,重点分析
median:中位数,把所有值从小到大排列,位置位于中间那个数
详细的分析结果:
Response:总的响应时间
time:该查询在本次分析中占用的时间比
Calls:执行次数
R/Call:平均每次执行的响应时间
Item:查询对象
每一条查询的详细分析结果:
ID:查询的ID号,和上图的Query ID对应
Databases: 数据库名
Users:执行的用户
Query_time distribution:查询的时间分布(此图说明,查询几乎都在1ms-10ms之间)
Tables:查询涉及到的表
EXPLAIN:SQL语句
4.用法示例
(1)直接分析慢查询文件:
pt-query-digest slow.log > slow_report.log
(2)分析最近12小时内的查询:
pt-query-digest --since=12h slow.log > slow_report2.log
(3)分析指定时间范围内的查询:
pt-query-digest slow.log --since '2014-04-17 09:30:00' --until '2014-04-17 10:00:00'> > slow_report3.log
(4)分析指含有select语句的慢查询
pt-query-digest--filter '$event->{fingerprint} =~ m/^select/i' slow.log> slow_report4.log
(5) 针对某个用户的慢查询
pt-query-digest--filter '($event->{user} || "") =~ m/^root/i' slow.log> slow_report5.log
(6) 查询所有所有的全表扫描或full join的慢查询
pt-query-digest--filter '(($event->{Full_scan} || "") eq "yes") ||(($event->{Full_join} || "") eq "yes")' slow.log> slow_report6.log
(7)把查询保存到query_review表
pt-query-digest --user=root –password=abc123 --review h=localhost,D=test,t=query_review--create-review-table slow.log
(8)把查询保存到query_history表
pt-query-digest --user=root –password=abc123 --review h=localhost,D=test,t=query_ history--create-review-table slow.log_20140401
pt-query-digest --user=root –password=abc123--review h=localhost,D=test,t=query_history--create-review-table slow.log_20140402
(9)通过tcpdump抓取mysql的tcp协议数据,然后再分析
tcpdump -s 65535 -x -nn -q -tttt -i any -c 1000 port 3306 > mysql.tcp.txt
pt-query-digest --type tcpdump mysql.tcp.txt> slow_report9.log
(10)分析binlog
mysqlbinlog mysql-bin.000093 > mysql-bin000093.sql
pt-query-digest --type=binlog mysql-bin000093.sql > slow_report10.log
(11)分析general log
pt-query-digest --type=genlog localhost.log > slow_report11.log
#快速安装
wget https://www.percona.com/downloads/percona-toolkit/2.2.16/RPM/percona-toolkit-2.2.16-1.noarch.rpm && yum localinstall -y percona-toolkit-2.2.16-1.noarch.rpm
#源码安装:
wget https://www.percona.com/downloads/percona-toolkit/2.2.14/tarball/percona-toolkit-2.2.14.tar.gz
tar -zxvf percona-toolkit-2.2.14.tar.gz
cd percona-toolkit-2.2.14
#cat Makefile.PL
#cat README
perl Makefile.PL
make
make test
make install
/usr/local/bin/pt-query-digest /opt/tuniu/mysql/data/slow-query.log
#新增环境变量
env
vi ~/.bash_profile
source ~/.bash_profile
使用
/usr/local/bin/pt-query-digest /opt/tuniu/mysql/data/slow-query.log
其他:
http://blog.csdn.net/wangmuming/article/details/38383449
http://www.ruzuojun.com/topic/592.html
工具使用简介:
1.查看服务器信息
# pt-summary
详细文档 :http://www.percona.com/doc/percona-toolkit/2.2/pt-summary.html
2.查看磁盘开销使用信息
# pt-diskstats
详细文档 :http://www.percona.com/doc/percona-toolkit/2.2/pt-diskstats.html
3.查看mysql数据库信息
# pt-mysql-summary --user=root --password=123456
详细文档 :http://www.percona.com/doc/percona-toolkit/2.2/pt-mysql-summary.html
4.分析慢查询日志
# pt-query-digest /data/mysql/data/db-3-12-slow.log
详细文档:http://www.percona.com/doc/percona-toolkit/2.2/pt-query-digest.html
5.查找mysql的从库和同步状态
# pt-slave-find --host=localhost --user=root --password=123456
详细文档 :http://www.percona.com/doc/percona-toolkit/2.2/pt-slave-find.html
6.查看mysql的死锁信息
# pt-deadlock-logger --user=root --password=123456 localhost
详细文档:http://www.percona.com/doc/percona-toolkit/2.2/pt-deadlock-logger.html
7.从慢查询日志中分析索引使用情况
# pt-index-usage slow_20131009.log
详细文档:http://www.percona.com/doc/percona-toolkit/2.2/pt-index-usage.html
8.查找数据库表中重复的索引
# pt-duplicate-key-checker --host=localhost --user=root --password=123456
详细文档:http://www.percona.com/doc/percona-toolkit/2.2/pt-duplicate-key-checker.html
9.查看mysql表和文件的当前活动IO开销
# pt-ioprofile
详细文档:http://www.percona.com/doc/percona-toolkit/2.2/pt-ioprofile.html
10.查看不同mysql配置文件的差异
# pt-config-diff /etc/my.cnf /etc/my_master.cnf
详细文档:http://www.percona.com/doc/percona-toolkit/2.2/pt-config-diff.html
11. pt-find查找mysql表和执行命令,示例如下
查找数据库里大于2G的表:
# pt-find --user=root --password=123456 --tablesize +2G
查找10天前创建,MyISAM引擎的表:
# pt-find --user=root --password=123456 --ctime +10 --engine MyISAM
查看表和索引大小并排序
# pt-find --user=root --password=123456 --printf "%T\t%D.%N\n" | sort -rn
详细文档:http://www.percona.com/doc/percona-toolkit/2.2/pt-find.html
12) pt-kill 杀掉符合标准的mysql进程
显示查询时间大于60秒的查询
# pt-kill --user=root --password=123456 --busy-time 60 --print
kill掉大于60秒的查询
# pt-kill --user=root --password=123456 --busy-time 60 --kill
详细文档:http://www.percona.com/doc/percona-toolkit/2.2/pt-kill.html
13) 查看mysql授权
# pt-show-grants --user=root --password=123456
# pt-show-grants --user=root --password=123456 --separate --revoke
详细文档:http://www.percona.com/doc/percona-toolkit/2.2/pt-show-grants.html
14)验证数据库复制的完整性
# pt-table-checksum --user=root --password=123456
问题
7
)
pt-query-digest /var/run/mysqld/mysqld-slow.log | more生成的报表,结构和内容?
分三部分:
第一部分:总体的情况。
第二部分:从表的角度。
第三部分:从具体sql角度。
[root@localhost media]# pt-query-digest /var/run/mysqld/mysqld-slow.log | more
# 180ms user time, 220ms system time, 22.41M rss, 198.73M vsz
# Current date: Sat Dec 29 05:30:52 2018
# Hostname: localhost.localdomain
# Files: /var/run/mysqld/mysqld-slow.log
//1,一共有多少条sql,不同的有多少条,
# Overall: 1 total, 1 unique, 0 QPS, 0x concurrency ______________________
//2,在这个时间范围内执行的sql语句。
# Time range: all events occurred at 2018-12-29 05:14:32
//3, 总体执行时间,执行时间最短的sql,执行时间最长的sql,sql执行的平均时间,95%的sql执行时间为814us。
# Attribute total min max avg 95% stddev median
# ============ ======= ======= ======= ======= ======= ======= =======
# Exec time 814us 814us 814us 814us 814us 0 814us
//4,锁定时间
# Lock time 285us 285us 285us 285us 285us 0 285us
//5,返回给客户端的行数
# Rows sent 2 2 2 2 2 0 2
//6 MySQL执行器需要扫描的行数行数
# Rows examine 2 2 2 2 2 0 2
// 7,查询大小
# Query size 28 28 28 28 28 0 28
//8,表的统计。
# Profile
# Rank Query ID Response time Calls R/Call V/M Item
# ==== ================== ============= ===== ====== ===== ============
# 1 0x48AB709485D784C3 0.0008 100.0% 1 0.0008 0.00 SELECT store
# Query 1: 0 QPS, 0x concurrency, ID 0x48AB709485D784C3 at byte 0 ________
# This item is included in the report because it matches --limit.
# Scores: V/M = 0.00
# Time range: all events occurred at 2018-12-29 05:14:32
//9,pct占总的时间,total所消耗时间。
# Attribute pct total min max avg 95% stddev median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count 100 1
# Exec time 100 814us 814us 814us 814us 814us 0 814us
# Rows sent 100 2 2 2 2 2 0 2
# Rows examine 100 2 2 2 2 2 0 2
# Query size 100 28 28 28 28 28 0 28
# String:
# Databases sakila
# Hosts localhost
# Users root
# Query_time distribution
# 1us
# 10us
# 100us ################################################################
# 1ms
# 10ms
# 100ms
# 1s
# 10s+
# Tables
# SHOW TABLE STATUS FROM `sakila` LIKE 'store'\G
# SHOW CREATE TABLE `sakila`.`store`\G
# EXPLAIN /*!50100 PARTITIONS*/
//执行的sql
select * from store limit 10\G
问题8)如何通过慢查询,找到需要优化的sql?
- I/O大的sql是通过扫描的行数看出来的。
- 未命中的索引sql ,如果扫描行数(rows examine) 远远大于 发送行(要执行的行数rows send)说明索引命中率不高。
问题9)通过sql的执行计划explain,找到需要优化的点?
如上:
id
id列数字越大越先执行;
如果说数字一样大,那么就从上往下依次执行,id列为null的就表示这是一个结果集,不需要使用它来进行查询。
----------------------------------
select_type
查询的序列号
A:simple:表示不需要union操作或者不包含子查询的简单select查询。有连接查询时,外层的查询为simple,且只有一个
B:primary:一个需要union操作或者含有子查询的select,位于最外层的单位查询的select_type即为primary。且只有一个
C:union:union连接的两个select查询,第一个查询是dervied派生表,除了第一个表外,第二个以后的表select_type都是union
D:dependent union:与union一样,出现在union 或union all语句中,但是这个查询要受到外部查询的影响
E:union result:包含union的结果集,在union和union all语句中,因为它不需要参与查询,所以id字段为null
F:subquery:除了from字句中包含的子查询外,其他地方出现的子查询都可能是subquery
G:dependent subquery:与dependent union类似,表示这个subquery的查询要受到外部表查询的影响
H:derived:from字句中出现的子查询,也叫做派生表,其他数据库中可能叫做内联视图或嵌套select
----------------------------------
table
显示的查询表名,如果查询使用了别名,那么这里显示的是别名;
如果不涉及对数据表的操作,那么这显示为null,
如果显示为尖括号括起来的<derived N>就表示这个是临时表,后边的N就是执行计划中的id,表示结果来自于这个查询产生。
如果是尖括号括起来的<union M,N>,与<derived N>类似,也是一个临时表,表示这个结果来自于union查询的id为M,N的结果集。
type
查询所使用的类型
依次从快到慢:system,const,eq_ref,ref,fulltext,ref_or_null,unique_subquery,index_subquery,range,index_merge,index,ALL,
除了all之外,其他的type都可以使用到索引,除了index_merge之外,其他的type只可以用到一个索引
A:system:
表中只有一行数据或者是空表,且只能用于myisam和memory表。
如果是Innodb引擎表,type列在这个情况通常都是all或者index
B:const:一般主键查找,或唯一索引查找,所以返回一行数据。
使用唯一索引或者主键,返回记录一定是1行记录的等值where条件时,通常type是const。
其他数据库也叫做唯一索引扫描
C:eq_ref:连表操作主表返回一行数据,并且连接条件是从表的主键或唯一索引。
出现在连接表的查询中,主表只返回一行数据,
且这行数据是包含从表的主键或者唯一索引,且必须为not null;
唯一索引和主键是多列时,只有所有的列都用作比较时才会出现eq_ref
D:ref:链表操作,主表不是唯一索引UNIQUE或主键PRIMARY KEY作为连接条件。 没有eq_ref要求严格,没有主键和唯一索引的要求、只要使用相等条件检索时就可能出现;
常见与辅助索引的等值查找。ref可以用于使用=或<=>操作符的带索引的列
主表返回数据不唯一的等值查找就可能出现。
E:full text:
全文索引检索,要注意,全文索引的优先级很高;
若全文索引和普通索引同时存在时,mysql不管代价,优先选择使用全文索引
F:ref_or_null:
与ref方法类似,只是增加了null值的比较。实际用的不多。
G:unique_subquery:
用于where中的in形式子查询,子查询返回不重复值唯一值
H:index_subquery:
用于in形式子查询使用到了辅助索引或者in常数列表,子查询可能返回重复值;
可以使用索引将子查询去重。
I:range:索引范围扫描;
常见于使用>,<,is null,between ,in ,like等运算符的查询中。
key列显示使用了哪个索引。key_len包含所使用索引的最长关键元素。在该类型中ref列为 NULL。当使用=、<>、>、>=、<、<=、IS NULL、<=>、BETWEEN或者IN操作符, 用常量比较关键字列时,可以使用range
J:index_merge:
表示查询使用了两个以上的索引,最后取交集或者并集,常见and ,or的条件使用了不同的索 引;
官方排序这个在ref_or_null之后,但是实际上由于要读取所个索引,性能可能大部分时间都不 如range
K:index:索引全表扫描,把索引从头到尾扫一遍;
常见于使用索引列就可以处理不需要读取数据文件的查询、可以使用索引排序或者分组的查询。
L:all:全表扫描查找数据;常见于没有where条件的语句。
然后再在server层进行过滤返回符合要求的记录。
----------------------------------
possible_keys:查询可能使用到的索引,如果为空没有相关的索引。
指出MySQL能使用哪个索引在该表中找到行。如果是空的,没有相关的索引。
这时要提高性能,可通过检验WHERE子句,看是否引用某些字段,或者检查字段不是适合索引。
注意,该列完全独立于EXPLAIN输出所示的表的次序。这意味着在possible_keys中的某些键实 际上不能按生成的表次序使用。
----------------------------------
Key:查询实际使用到的索引。
select_type为index_merge时,这里可能出现两个以上的索引,其他的select
要想强制MySQL使用或忽视possible_keys列中的索引,在查询中使用FORCE INDEX、USE INDEX或者IGNORE INDEX。
----------------------------------
key_len :用于处理查询的索引长度;越短越好、速度越快;
如果是单列索引,那就整个索引长度算进去;
如果是多列索引,那么查询不一定都能使用到所有的列,具体使用到了多少个列的索引,这里就会计算进去,没有使用到的列,这里不会计算进去;
留意下这个列的值,算一下你的多列索引总长度就知道有没有使用到所有的列了。
要注意,mysql的ICP特性使用到的索引不会计入其中。
另外,key_len只计算where条件用到的索引长度,而排序和分组就算用到了索引,也不会计算到key_len中。
----------------------------------
Ref : 显示索引的那一列被使用了。最好的情况是一个常数。
如果是使用的常数等值查询,这里会显示const;
如果是连接查询,被驱动表的执行计划这里会显示驱动表的关联字段;
如果是条件使用了表达式或者函数,或者条件列发生了内部隐式转换,这里可能显示为func;
----------------------------------
Rows:显示MySQL认为它执行sql计划时必须检查的行数,不是精确值
这里是执行计划中估算的扫描行数,不是精确值;
----------------------------------
Filtered:
使用explain extended时会出现这个列;
5.7之后的版本默认就有这个字段,不需要使用explain extended了。
这个字段表示存储引擎返回的数据在server层过滤后,剩下多少满足查询的记录数量的比例,注意是百分比,不是具体记录数。
----------------------------------
Extra:一般出现using filesort,using temporary表示使用了临时文件或外部文件,进行存储结果,都需要优化。
这个列可以显示的信息非常多,有几十种,常用的有:
A:distinct:
在select部分使用了distinc关键字
B:no tables used:
不带from字句的查询或者From dual查询
C:using filesort:用到了文件排序,
排序时无法使用到索引时,就会出现这个。常见于order by和group by语句中
E:using index:
查询时不需要回表查询,直接通过索引就可以获取查询的数据。
F:using join buffer(block nested loop),using join buffer(batched key accss):
5.6.x之后的版本优化关联查询的BNL,BKA特性。主要是减少内表的循环数量以及比较顺序地扫描查询。
G:using sort_union,using_union,using intersect,using sort_intersection:
using intersect:表示使用and的各个索引的条件时,该信息表示是从处理结果获取交集
using union:表示使用or连接各个使用索引的条件时,该信息表示从处理结果获取并集
using sort_union和using sort_intersection:与前面两个对应的类似,只是他们是出现在用and和or查询信息量大时,先查询主键,然后进行排序合并后,才能读取记录并返回。
H:using temporary:表示这个sql用到了临时表。
表示使用了临时表存储中间结果。临时表可以是内存临时表和磁盘临时表,执行计划中看不出来,需要查看status变量,used_tmp_table,used_tmp_disk_table才能看出来。
I:using where:
表示存储引擎返回的记录并不是所有的都满足查询条件,需要在server层进行过滤。
查询条件中分为限制条件和检查条件,
5.6之前,存储引擎只能根据限制条件扫描数据并返回,然后server层根据检查条件进行过滤再返回真正符合查询的数据。
5.6.x之后支持ICP特性,可以把检查条件也下推到存储引擎层,不符合检查条件和限制条件的数据,直接不读取,这样就大大减少了存储引擎扫描的记录数量。
extra列显示using index condition
J:firstmatch(tb_name):
5.6.x开始引入的优化子查询的新特性之一,常见于where字句含有in()类型的子查询。如果内表的数据量比较大,就可能出现这个
K:loosescan(m..n):
5.6.x之后引入的优化子查询的新特性之一,在in()类型的子查询中,子查询返回的可能有重复记录时,就可能出现这个
除了这些之外,还有很多查询数据字典库,执行计划过程中就发现不可能存在结果的一些提示信息
问题10)对Count()使用和Max()的优化,通过建立索引?
例子:max();优化
如下:type为ALL,表的全扫描。扫描行数rows为15522。如果sql数据库比较大,io比较高的时候,这是会拖慢查询速度的。
第一步:mysql> explain select max(payment_date) from payment \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: payment
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 15522
Extra:
1 row in set (0.00 sec)
第二步:可以通过建立索引:再看看sql的执行计划。
Create index 索引名称 on 表名(字段);
mysql> create index idx_paydate on payment(pay_date);
第三步:再次查看执行计划:table为null,可以发现,它并没有查询表,而是同索引直接进行查询。(因为索引是顺序排列的,索引很容易查询)
mysql> explain select max(payment_date) from payment \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: NULL
type: NULL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: NULL
Extra: Select tables optimized away
1 row in set (0.00 sec)
例子:count()注意事项。Count(*)和count(字段) 区别 ?
Count(*)包含某字段为null的行。
Count(字段) 如果该字段不null,不会计数。
查询2006年电影数和2007年电影数。
mysql> select count(release_year='2006' or NULL) as '2006_count',count(release_year='2007') as '2007_count' from film;
问题11)子查询的优化和group by优化?
- 把子查询转换成join连接方式。转换成join连接的时候要注意重复数据,通过distinct去重复。
1,group by 要先分组排序,然后再进行连接。就不会生成临时表。
问题12)limit进行优化?
- limit一般都是和order by排序一起使用。
- 优化步骤一:order by条件建立索引。
- 优化步骤二:对limit进行限制,不要直接写,limit 从第几开始,取几行。这样会扫描前面是所有行数。应该添加where条件,where条件设置大于或小于,这样就不会进行扫描limit之前的行。
索引优化
问题13)索引的优化
- 索引建立在where条件上,group by,order by,on添加后面。
- 索引字段长度越小越好,因为数据库表是页存储的,(一页上索引越多越好)
3,离散度大(重复数据少的离散度大distinct)的列放到联合索引前面。
问题14)哪些索引需要删除?
1,建立索引有利于查询,但是不利于增加和删除,修改等操作。
所以索引不是越多越好。
- 冗余索引是指的:如果该列本来就是索引,建立联合索引时候,又将该索引包含在里面,就形成了冗余索引。Innodb数据库引擎会自动创建主键为唯一索引。
问题15)去掉冗余索引的工具:
pt-duplicate-key-checker --u=root --p='root' --h=127.0.0.1 --databases=mall
问题16)删除使用频率低,或不适用的索引?
如何知道索引的使用频率呢?
注意:在进行慢查询日志查看索引的使用情况的时候,需要把主表和从表一起分析,这样不会漏掉,如果只是某个从表不适用该索引,但是其他从表还在使用该索引,就不能删除这个索引。
数据库和表结构优化
问题17)选择合适的数据类型?
- 尽量少用text类型,非用不可最好考虑分表。
- 尽可能的使用not null 定义字段。NULL 其实并不是空值,而是要占用空间,所以mysql在进行比较的时候,NULL 会参与字段比较,所以对效率有一部分影响
- 使用可以存下你的数据的最小的数据类型。因为int要比varchar在mysql上处理简单。
用int类型来存储时间:
用bigint存储ip地址。
问题18)创建符合第三范式的数据表结构?
第三范式指的:不存在传递依赖。
问题19)数据库三范式,及部分依赖,完全依赖,传递依赖?
第一范式:每一列都是不可分割的原子数据项,
第二范式:要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性。
第三范式:任何非主属性不依赖于其它非主属性(在2NF基础上消除传递依赖)
部分函数依赖:设X,Y是关系R的两个属性集合,存在X→Y,若X’是X的真子集,存在X’→Y,则称Y部分函数依赖于X。
举个例子:通过AB能得出C,通过A也能得出C,通过B也能得出C,那么说C部分依赖于AB。
完全函数依赖:设X,Y是关系R的两个属性集合,X’是X的真子集,存在X→Y,但对每一个X’都有X’!→Y,则称Y完全函数依赖于X。
举个例子:通过AB能得出C,但是AB单独得不出C,那么说C完全依赖于AB.
传递函数依赖:设X,Y,Z是关系R中互不相同的属性集合,存在X→Y(Y !→X),Y→Z,则称Z传递函数依赖于X。
举个例子:通过A得到B,通过B得到C,但是C得不到B,B得不到A,那么成C传递依赖于A
第三范式(3NF):在第二范式的基础上,数据表中如果不存在非关键字段对任一候选关键字段的传递函数依赖则符合第三范式。所谓传递函数依赖,指 的是如果存在”A → B → C”的决定关系,则C传递函数依赖于A。因此,满足第三范式的数据库表应该不存在如下依赖关系:
关键字段 → 非关键字段x → 非关键字段y
假定学生关系表为Student(学号, 姓名, 年龄, 所在学院, 学院地点, 学院电话),关键字为单一关键字”学号”,因为存在如下决定关系:
(学号) → (姓名, 年龄, 所在学院, 学院地点, 学院电话)
这个数据库是符合2NF的,但是不符合3NF,因为存在如下决定关系:
(学号) → (所在学院) → (学院地点, 学院电话)
即存在非关键字段”学院地点”、”学院电话”对关键字段”学号”的传递函数依赖。
它也会存在数据冗余、更新异常、插入异常和删除异常的情况,读者可自行分析得知。
把学生关系表分为如下两个表:
学生:(学号, 姓名, 年龄, 所在学院);
学院:(学院, 地点, 电话)。
这样的数据库表是符合第三范式的,消除了数据冗余、更新异常、插入异常和删除异常。
鲍依斯-科得范式(BCNF):在第三范式的基础上,数据库表中如果不存在任何字段对任一候选关键字段的传递函数依赖则符合第三范式。
假设仓库管理关系表为StorehouseManage(仓库ID, 存储物品ID, 管理员ID, 数量),且有一个管理员只在一个仓库工作;一个仓库可以存储多种物品。这个数据库表中存在如下决定关系:
(仓库ID, 存储物品ID) →(管理员ID, 数量)
(管理员ID, 存储物品ID) → (仓库ID, 数量)
所以,(仓库ID, 存储物品ID)和(管理员ID, 存储物品ID)都是StorehouseManage的候选关键字,表中的唯一非关键字段为数量,它是符合第三范式的。但是,由于存在如下决定关系:
(仓库ID) → (管理员ID)
(管理员ID) → (仓库ID)
即存在关键字段决定关键字段的情况,所以其不符合BCNF范式。它会出现如下异常情况:
(1) 删除异常:
当仓库被清空后,所有”存储物品ID”和”数量”信息被删除的同时,”仓库ID”和”管理员ID”信息也被删除了。
(2) 插入异常:
当仓库没有存储任何物品时,无法给仓库分配管理员。
(3) 更新异常:
如果仓库换了管理员,则表中所有行的管理员ID都要修改。
把仓库管理关系表分解为二个关系表:
仓库管理:StorehouseManage(仓库ID, 管理员ID);
仓库:Storehouse(仓库ID, 存储物品ID, 数量)。
这样的数据库表是符合BCNF范式的,消除了删除异常、插入异常和更新异常。
问题17)为什么要反范式化?
引用符合第三范式的表,如果在进行查询多个信息的时候,需要进行多表查询。这样会增加开销。所以为了方便查询,会适当的增加冗余,来减少多表连接的操作。
例如:
问题18)表的垂直拆分?
垂直拆分原因:表的字段比较多,字段内容比较大。
根据下面三个基本的原则进行拆表操作:
问题19)表的水平拆分?
拆分的原因:表的数据量比较大。
拆分原则:拆成5个表,根据表id,进行取模,余数为1,的在表1。余数为2的在表2中等。
拆分之后:如何查询数据呢?
前端查询用拆分之后的表,每个表平均查询几条。(提高效率,实时性)
后端的查询,还是用汇总未拆分的表。
问题20)操作系统的系统优化?
问题21)mysql配置文件的优化?
- 一般可以通过启动时的配置文件进行优化。
- 使用的配置文件进行优化。
- 文件位置。
- 通过
第三方的配置优化建议:
问题17)Linux下的Mysql用命令执行sql文件
1,将要导入的.sql文件移至bin文件下,这样的路径比较方便
2,同上面导出的第1步
3,进入MySQL:mysql -u 用户名 -p
如我输入的命令行:mysql -u root -p (输入同样后会让你输入ySQL的密码)
4,在MySQL-Front中新建你要建的数据库,这时是空数据库,如新建一个名为blog的目标数据库(mysql>create database blog;)
5,输入:mysql>use 目标数据库名
如我输入的命令行:mysql>use blog;
6,导入文件:mysql>source 导入的文件名;
如我输入的命令行:mysql>source table.sql;