将关系模式看做三个元组:R
R:关系名;U:一组属性;F:属性组U上的一组数据依赖。
当且仅当一个关系r满足F时,r称关系模式R的一个关系。
数据依赖:一个表内部属性与属性间的约束关系。其中最重要的是函数依赖(FD)与多值依赖(MVD)。
数据冗余。浪费存储空间。
更新异常。
插入异常。该插入的数据插不进去。
删除异常。不该删除的数据也删去了。
定义。设R(U)是一个属性集U上的关系模式,X和Y是U的子集。若对于R(U)的任意一个可能的关系r,r中不可能存在两个元组在X上的属性值相等,而在Y上的属性值不等,则称X函数确定Y或Y函数依赖于X,记作X- >Y。
例:学号->姓名。
X- >Y,Y不包含X,X->Y是非平凡的函数依赖。如(学号,课程编号)->分数。
在关系模式R(U)中,如果X- >Y,并且对于X的任何一个真子集X’,X’不函数依赖于Y,称Y完全函数依赖于X[(学号,课程号)->成绩],若 X- >Y,但Y不完全函数依赖于X,则称Y部分函数依赖于X[(学号,课程号)->所在系]。
如:
1NF:如果一个关系模式R的所有属性都是不可分的基本数据项。
2NF:关系模式R∈1NF,且每一个非主属性都完全函数依赖于R的码,则R∈2NF。
如:
所在系,“宿舍楼”部分函数依赖于码。(不满足2NF)
解决:投影分解法。(满足2NF)
2NF存在问题:
插入异常:如:新成立一个系还未招收学生,则无法存入。
删除异常。
修改复杂:一个系更改宿舍,该系所有学生都要修改一遍。
原因:
“宿舍楼”传递函数依赖于“学号”,即:非主属性传递函数依赖码。
解决:投影分解法。
3NF:关系模式R∈1NF,若R中不存在这样的码X、属性组Y及非主属性Z (Z不属于Y),使得X- >Y, Y- >Z, Y- >X,成立,则称R∈3NF。
例
候选码:(学号,课程)和(学号,导师),不存在非主属性对码的部分函数依赖和传递依赖。
BCNF。关系模式R∈1NF,如果对于R的每个函数依赖X- >Y,且X不包含Y时,X必含有码,那么R∈BCNF。(把三元联系尽量将为二元)。
事务是访问并可能更新各种数据项的一个程序执行单元,也可以说是一组原子性的SQL查询。
案例:
银行的数据库有两张表:支票(checking)表和储蓄(savings) 表。现在要从用户Jane的支票账户转移200美元到她的储蓄账户,需要至少三个步骤:
1.检查支票账户的余额高于200美元。
2.从支票账户余额中减200美元。
3.在储蓄账户余额中加200美元。
上述三个步骤的操作必须在一个事务中,任何一个步骤失败,则必须回滚所有的步骤。
用START TRANSACTION语句开始一个事务,使用COMMIT提交事务将修改的数据持久保留,或使用ROLLBACK撤销所有的修改。事务SQL的样本如下:
START TRANSACTION;
SELECT balance FROM checking WHERE customer_id = 10233276;
UPDATE checking SET balance = balance - 200.00 WHERE customer_id = 10233276;
UPDATE savings SET balance = balance + 200.00 WHERE customer_id = 10233276;
COMMIT;
原子性(atomicity)。整个事务中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作。
一致性 (consistency)。数据库总是从一个一致性的状态转换到另外一个一致性的状态。
在前面的例子中,即使在执行第三、四条语句之间时系统崩溃,支票账户中也不会损失200美元,因为事务最终没有提交,所以事务中所做的修改也不会保存到数据库中。
隔离性(isolation)。通常来说,一个事务所做的修改在最终提交以前,对其他事务是不可见的。
在前面的例子中,当执行完第三条语句、第四条语句还未开始时,此时有另外一个账户汇总程序开始运行,则其看到的支票账户的余额并没有被减去200美元。
持久性(durability)。一旦事务提交,则其所做的修改就会永久保存到数据库中。此时即使系统崩溃,修改的数据也不会丢失。
持久性是个有点模糊的概念,因为实际上持久性也分很多不同的级别。有些持久性策略能够提供非常强的安全保障,而有些则未必。而且不可能有能做到100%的持久性保证的策略。
-- 设置隔离级别(只改变当前会话)
SET SESSION TRANSACTION ISOLATION LEVEL 隔离级别;
READ UNCOMMITTED (未提交读)。在这个隔离级别,事务中的修改,即使没有提交,对其他事务也都是可见的。事务可以读取未提交的数据,也被称为脏读(Dirty Read)。从性能上来说,不会比其他的级别好太多,但却缺乏其他级别的很多好处,在实际应用中很少使用。
READ COMMITTED (提交读)。大多数数据库系统的默认隔离级别(MySQL不是)。满足隔离性的简单定义:一个事务从开始直到提交之前,所做的修改对其他事务都是不可见的。也叫不可重复读(nonrepeatableread),因为两次执行同样的查询,可能会得到不样的结果。
REPEATABLE READ (可重复读)。解决了脏读的问题,MySQL默认事务隔离级别。保证了在同一个事务中多次读取同样记录的结果是一致的。但无法解决幻读(Phantom Read) 的问题。
幻读,指事务a在读取某个范围内的记录时,事务b在该范围内插入了新的记录,事务a再次读取该范围的记录时,会产生幻行(Phantom Row),即事务b插入的新记录。
InnoDB和XtraDB存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)解决了幻读的问题。
SERIALIZABLE (可串行化)。最高的隔离级别。通过强制事务串行执行,避免了幻读。SERIALIZABLE 会在读取的每一行数据上都加锁,可能导致大量的超时和锁争用的问题。实际应用中很少使用。只有在需要确保数据的一致性且可以接受没有并发的情况下,才考虑使用。
自动提交(AUTOCOMMIT)
MySQL默认采用自动提交(AUTOCOMMIT) 模式。即如果不是显式地开始一个事务,则每个查询都被当作一个事务执行提交操作。
在当前连接中,可以通过设置AUTOCOMMIT变量来启用或者禁用自动提交模式:
-- 查看自动提交
SHOW VARIABLES LIKE 'AUTOCONMIT';
-- 设置(1启用,0禁用)
SET AUTOCOMMIT = 1;
索引是一种排好序的快速查找的数据结构
CREATE INDEX 索引名 ON 表名(属性);
CREATE UNIQUE INDEX 索引名 ON 表名(属性);
-- 删除索引
DROP INDEX 索引名 ON 表名;
多分平衡树,存取效率高;既能随机查找、又能顺序查找;增删改操作,保持平衡。
选择Hash存取方法的规则
如果一个关系的属性主要出现在等值连接条件中或主要出现在等值比较选择条件中,而且满足下列两个条件之一:
关系的大小可预知,而且不变;
关系的大小动态改变,但所选用的数据库管理系统提供了动态Hash存取方法。
-- 现在已提供存储引擎:
show engines;
-- 当前默认的存储引擎:
show variables like '%storage_engine%';
读取顺序
FROM <left table>
ON <join_condition>
<join_type> JOIN <right_table>
WHERE <where_condition>
GROUP BY <group_by_list>
HAVING <having_condition>
SELECT
DISTINCT <select_list>
ORDER BY <order_by_condition>
LIMIT <limit_nunber>
-- 1、
SELECT <select_list>
FROM table1 a INNER JOIN table2 b
ON a.key=b.key;
-- 2、
SELECT <select_list>
FROM table1 a LEFT JOIN table2 b
ON a.key=b.key;
-- 3、
SELECT <select_list>
FROM table1 a LEFT JOIN table2 b
ON a.key=b.key
WHERE b.key IS NULL;
-- 4、
SELECT <select_list>
FROM table1 a RIGHT JOIN table2 b
ON a.key=b.key;
-- 5、
SELECT <select_list>
FROM table1 a RIGHT JOIN table2 b
ON a.key=b.key
WHERE b.key IS NULL;
-- 6、
SELECT <select_list>
FROM table1 a OUTER JOIN table2 b
ON a.key=b.key;
--7、
SELECT <select_list>
FROM table1 a OUTER JOIN table2 b
ON a.key=b.key
WHERE a.key IS NULL
OR
b.key IS NULL;
-- musql 不支持全外连接
SELECT * FROM table1 a LEFT JOIN table2 b on a.key = b.key
UNION
SELECT * FROM table1 a RIGHT table2 b on a.key = b.key;
SELECT * FROM table1 a LEFT JOIN table2 b on a.key = b.key
WHERE b.key is NULL
UNION
SELECT * FROM table1 a RIGHT table2 b on a.key = b.key
WHERE a.ket IS NULL;
索引是一种排好序的快速查找的数据结构。系引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上。
优势:提高数据检索的效率,降低数据库的IO成本;降低数据排序的成本,降低了CPU的消耗。
单值索引。一个索引只包含单个列。
唯一索引。索引列的值唯一 ,允许空值。
复合索引。一个索引包含多个列。
基本语法。
CREATE INDEX 索引名 ON 表名(属性);
CREATE UNIQUE INDEX 索引名 ON 表名(属性);
ALTER 表名 ADD [UNIQUE ] INDEX [索引名] ON (属性);
-- 删除索引
DROP INDEX 索引名 ON 表名;
-- 查看
SHOW INDEX FROM table_name;
需要创建索情况
主键自动建立唯一索引;
频繁作为查询条件的字段应该创建索引;
查询中与其它表关联的字段,外键关系建立索引;
频繁更新的字段不适合创建索引;
Where条件里用不到的字段不创建索引;
查询中统计或者分组字段;
查询中排序的字段,排序字段若通过索引去访问提高排序速度。
需要创建索情况
经常增删改的表;
数据重复且分布平均的表字段。
MYSQL瓶颈。
CPU:CPU在饱和的时候一般发生在数据装入内存或从磁盘上读取数据时候
IO:磁盘I/0瓶颈发生在装入数据远大于内存容量的时候
服务器硬件的性能瓶颈:top,free,iostat和vmstat来查看系统的性能状态。
EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理SQL语句的。分析查询语句或是表结构的性能瓶颈。
Explain+SQL语句
表的读取顺序
数据读取操作的操作类型
哪些索引可以使用
哪些索引被实际使用
表之间的引用
每张表有多少行被优化器查询
id字段
id相同,读取顺序由上至下。
id不同,id大先读取。
id大先读取; id相同,读取顺序由上至下。
select_type |
---|
SIMPLE(简单的查询,语句中不含子查询或者UNION) |
PRIMARY(查询中包含复杂的子部分,最外层的表标记为PRIMARY) |
SUBQUERY(SELECT或WHERE列表中包含了子查询,子查询中的表标记) |
DERIUED(在FROM列表中包含的子查询标记为DERIVED,MySQL会递归执行这些子查询,把结果放在临时表。) |
UNION(若第二个SELECT出现在UNION之后,则第二个SELECT最外层表标记;若UNION包含在FROM子句的子查询中,外层SELECT将被标记为:DERIVED) |
UNION RESULT(从UNION表获取结果的SELECT) |
partitions
代表分区表中的命中情况,非分区表,该项为null。
typt
访问类型
从好到坏(常见):system > const > eq_ref > ref > range > index > ALL
一般来说,至少达到range级别, 最好能达到ref。
possible_ keys
显示可能应用在这张表中的索引,一个或多个查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询实际使用。
key
实际使用的索引。如果为NULL,则没有使用索引。
查询中若使用了覆盖索引,则该索引仅出现在key列表中
key_len
表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度。在不损失精确性的情况下,长度越短越好key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是 根据表定义计算而得,不是通过表内检索出的。
ref
显示索引的哪一列被使用了, 如果可能的话,是一个常数。哪些列或常量被用于查找索引列上的值
rows
根据表统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数。
Extra
包含重要的额外信息。
单表。
双表。左(右)连接,加右(左)表索引。
三表。类似于双表。
尽可能减少Join语句中的NestedLoop的循环总次数;“永远用小结果集驱动大的结果集”。
优先优化NestedLoop的内层循;
保证Join语句中被驱动表上Join条件字段已经被索引;
当无法保证被驱动表的Jgin条件字段被索引且内存资源充足的前提下,不要太吝惜JoinBuffer的设置;
ORDER BY子句,尽量使用Index方式排序,避免使用FileSort方式排序。
尽可能在索引列上完成排序操作,遵照索引建的最佳左前缀。
groupby实质是先排序后进行分组,遵照索引建的最佳左前缀.
当无法使用索引列,增大max_length_for _sort_data 参数的设置+增大sort_buffer_size参数的设置。
where高于having,能写在where限定的条件就不要去having限定了。
MySQL的慢查询日志是MySQL提供的一种日志记录,用来记录在MySQL中响应时间超过阈值的语句,具体指运行时间超过long_query_time值的SQL,则会被记录到慢查询日志中。
long_query_time的默认值为10, 意思是运行10秒以上的语句。
默认情况下,MySQL数据库没有开启慢查询日志,一般不建议启动该参数, 因为开启慢查询日志会或多或少带来一定的性能影响。慢查询日志支持将日志记录写入文件。
-- 查看
SHOW VARIABLES LIKE '%slow_query_log%';
-- 开启(关闭0)
set global slow_query_log=1;
-- 默认时间查看
SHOW VARIABLES LIKE 'long_query_time%';
-- 修改时间(从新连接可看到变化)
set global long_query_time=3;
-- 查看慢sql
show global status like '%Slow_queries%';
set global slow_query_log=1开启对当前数据库生效,MySQl重启后失效。
更改配置文件(永久生效)
slow_query_log=1;
slow_query_log_file=/var/ib/mysql/filename.log
long_query_ime=3;
log_output=FILE
mysqldumpslow。日志分析工具
如:得到返回记录集最多的10个SQL
mysqldumpslow -s r -t 10 /var/ib/mysql/atguigu-slow.log
是mysq|提供可以用来分析当前会话中语句执行的资源消耗情况。可以用于SQL的调优的测量。
默认情况下,参数处于开启状态,并保存最近15次的运行结果。
-- 查看开关状态
Show variables like 'profiling';
-- 查看sql
show profiles;
出现如下数据项(性能下降):
converting HEAP to MyISAM 查询结果太大,内存都不够用了往磁盘上搬了。
Creating tmp table 创建临时表
Copying to tmp table on disk 把内存中临时表复制到磁盘。
locked
锁是计算机协调多个进程或线程并发访问某一资源的机制。
锁的分类
从对数据操作的类型(读\写)
从对数据操作的粒度分:表锁(偏读)、行锁(偏写)。
-- 加锁
lock table 表名 read(write),[表名2 read(write)];
-- 查看表的锁信息
show open tables;
-- 解锁
unlock tables;
偏向MyISAM存储引擎,开销小,加锁快;无死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
MyISAM在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁,在执行增删改操作前,会自动给涉及的表加写锁。
结论:
对MyISAM表进行操作:
1、对MyISAM表的读操作(加读锁),不会阻塞其他进程对同一表的读请求,但会阻塞对同一表的写请求。只有当读锁释放后,
才会执行其它进程的写操作。
2、对MyISAM表的写操作(加写锁),会阻塞其他进程对同一表的读和写操作,只有当写锁释放后,才会执行其它进程的读写操作。
即。读锁会阻塞写,但是不会堵塞读。而写锁则会把读和写都堵塞。
偏向InnoDB存储引擎,开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
InnoDB与MyISAM的最大不同有两点:1、支持事务(TRANSACTION);2、采用了行级锁
-- 查看数据库事务隔离级别
show variables like 'tx_isolation';
无索引(索引失效)行锁升级为表锁。
间隙锁。用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给 符合条件的已有数据记录的索引项加锁;对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)”,这种锁机制就是所谓的间隙锁(Next-Key锁) 。
[危害]
当锁定一一个范围键值之后,即使某些不存在的键值也会被无辜的锁定,而造成在锁定的时候无
法插入锁定键值范围内的任何数据。
查看行锁情况
show status like 'innodb_row_lock%';
参数说明
Innodb_row_lock_current_waits:当前正在等待锁定的数量;
Innodb_row_lock_time:从系统启动到现在锁定总时间长度;
Innodb_row_lock_time_avg:每次等待所花平均时间;
Innodb_row_lock_time_max:从系统启动到现在等待最常的一次所花的时间;
Innodb_row_lock_waits:系统启动后到现在总共等待的次数。