mysql
数据库是被广泛应用的关系型数据库,体积小、支持多处理器、开源并免费的特性使其在中小型网站中的使用率尤其高。
分三个个方面:
#一、库表设计
mysql
常用引擎包括:MYISAM
、Innodb
、Memory
、MERGE
MYISAM
:全表锁,拥有较高的执行速度,不支持事务,不支持外键,并发性能差,占用空间相对较小,对事务完整性没有要求,以select、insert为主的应用基本上可以使用这引擎Innodb
:行级锁,提供了具有提交、回滚和崩溃回复能力的事务安全,支持自动增长列,支持外键约束,并发能力强,占用空间是MYISAM的2.5倍,处理效率相对会差一些Memory
:全表锁,存储在内容中,速度快,但会占用和数据量成正比的内存空间且数据在mysql
重启时会丢失,默认使用HASH索引,检索效率非常高,但不适用于精确查找,主要用于那些内容变化不频繁的代码表MERGE
:是一组MYISAM表的组合绝大部分是选用
innodb
引擎,特殊业务再考虑MYISAM
、Memory
,例如全文索引或极高的执行效率
在数据库使用过程中,为了减小数据库服务器的负担、缩短查询时间,会考虑做分表设计
分表分为两种:一种是纵向分表(将本来可以在同一个表的内容,认为划分存储为多个不同结构的表)和横向分表(把大的表结构,横向切割为同样结构的不同表)
常见的分表方式:根据活跃度、重要性分表,主要解决如下问题:
根据某些特定规则来划分数据量表,主要解决如下问题:
索引是对数据库表中一个或多个列的值进行排序的结构,建立索引有助于快速获取信息。
mysql
有4种不同的索引:
索引并非是越多越好,创建索引也需要耗费资源,一是增加了数据库的存储空间,二是在插入和删除时要花费较多的时间维护索引
#二. 慢SQL的问题
从出现的概率由大到小如下:
需要注意与索引有关的规则:
问:一张表,里面id自增长主键,已经向表中插入了10条数据之后,删除了8,9,10的记录,再把mysql
重启,之后再插入一条数据,那么数据id值是多少,8还是11.
四个基本要素(acid):原子性
、一致性
、隔离性
、持久性
原子性
(Actomicity):整个事务中的操作要么全完成,要么全部不完成,不能滞留在中间某个环节,事务在执行过程发生错误,会被回滚(Rollback)到事务开始前的状态,就像没执行过一样一致性
(Consistent):在事务开始和结束之后,数据库的完整性约束没有被破坏隔离性
(Isolation):使事务在给定的时间内执行的唯一操作,为了防止事务之间的混淆,必须串行化或序列化请求,使得在同一时间内仅有一个请求用于同一数据持久性
(Durable):在事务完成以后,该事务所对数据库所做的更改持久保存到数据库之中,并不会被回滚drop直接删掉表、truncate删除表中的数据,再插入数据自增长id又从1开始、delete删除表中的数据,可以加where语句
索引是数据库管理系统中一个排序的数据结构,已助快速查询、更新数据库表中数据,创建语句alter table tablename add index(id);
内连接
:
说明:组合两个表中的记录,返回关联字段的记录,返回两个表交集部分
左连接
:
说明:left join 是left outer join的简写,左外连接是外连接的一种,左外连接:左表的数据全显示,右表显示符合搜索条件的记录,右表记录不足的地方均为null
右连接
:
说明:right join 是right outer join的简写,右外连接是外连接的一种,右外连接:右表的数据全显示,左表显示符合搜索条件的记录,左表记录不足的地方均为null
全连接
:
目前mysql不支持
加锁原因:放置更新丢失,并不能单靠数据库事务控制器来解决,需要应用程序对更新的数据加必要的锁来解决
表级锁
:每次操作都锁定在整张表,开销少,加锁块,不会出现死锁,锁定粒度大,发生锁冲突的概率最高,并发度最低行级锁
:每次操作锁定一行数据,开销大,加锁慢,会出现死锁,锁定粒度小,发生锁冲突的概率最低,并发度最高页面锁
:开销和加锁时间介于两者之间,会出现死锁,并发度一般悲观锁
:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作乐观锁
:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性
乐观锁
更适合解决冲突概率极小的情况,而悲观锁
则适合解决并发竞争激烈的情况,尽量使用行锁
,缩小加锁粒度,以提高并发处理能力,即使加行锁
的时间比表锁
要长
相对于串行处理来说,并发事务处理能大大增加数据库资源的利用率,提高数据库系统的事务吞吐量,从而可以支持更多的用户
更新丢失
:当两个或多个事务选择同一行,然后基于最初的值选定该行进行更新该行时,由于事务之间没有联系,就会发生丢失更新的问题,如果在一个编辑人员完成并提交事务之前,另一个编辑人员不能访问同一个文件,就可以避免这类问题脏读
:一个事务在对一条数据进行修改,在事务完成并提交前,记录就处于不一致的状态,这是另外一个事务也来读取同一条记录,如果不加以控制,第二个事务读取了这些“脏”数据,并据此做进一步处理,就会产生未提交数据的依关系不可重复读
:一个事务在读取某些数据后的某个时间在,再次读取的时候,发现数据发生改变,或者某些记录被删除了幻读
:一个事务按相同的查询条件重复读取以前检索过的数据,却发现了其它事务插入了满足其查询条件的新数据跟新丢失可以通过加锁来解决,“脏读”、“不可重复读”、“幻读”属于数据库一致性问题,由数据库提供一定的事务隔离机制来解决
多版本并发控制
简称MVCC或MCC数据库的隔离越严格,并发副作用越小,付出的代价也就越大,隔离的实质就是在一定程度上使事务“串行化”,这显然与“并发”是矛盾的
隔离级别 | 读取数据一致性 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|---|
未提交读(Read uncommitted) | 最低级别,只能保证读取不损坏数据 | 是 | 是 | 是 |
已提交读(Read committed) | 语句级 | 否 | 是 | 是 |
可重复读(Repeatable read) | 事务级 | 否 | 否 | 是 |
可序列化(Serializable) | 最高级别,事务级 | 否 | 否 | 否 |
InnoDB在做SELECT的时候,要维护的东西比MyISAM引擎多
是基于索引
来完成行锁
例如:select * from a_table where id = 1 for update;
for update 可以根据条件来完成行锁定,并且id是有索引键的列,如果id不是索引键,那么innodb将完成表锁
1、为查询缓存优化查询
当很多相同的查询被执行了多次的时候,这些结果会被放到一个缓存中,这样后续的查询就直接访问缓存结果。
需要使用一个变量来代替 MYSQL 的函数,从而开启缓存
2、explain select 语句
explain 显示了 mysql 如何使用索引处理 select 语句及连接表,可以帮助选择更好的索引和写出更优化的查询语句
explain select * from table a;
3、当只要一行数据时使用 LIMIT 1
当查询表的时候,已经知道只会有一条结果,加上 LIMIT 1 后,MySQL 引擎会在查找到一条数据之后停止搜索
select 1 from user where id = 1 limit 1;
4、为搜索字段建索引
**5、避免使用 select ***
6、为每张表设置一个主键
应该为每张表都设置一个 ID 作为主键,而且最好是 INT 型的,并设置 auto_increment 自增长,使用 VARCHAR 作为主键会是性能下降;但是关联表的外键除外
7、使用 ENUM 而不是 VARCHAR
ENUM 类型是非常快和紧凑的,实际上,其保存的是 TINYINT,其外表上显示为一个字符串,当知道一些字段的取值是有限而且固定的,应该使用 ENUM
8、使用 procedure analyse() 取得建议
procedure analuse() 会让 MYSQL 帮你去分析字段和其实际数据,并会给一些建议,数据越多,建议就越准确
9、尽可能使用 not null
null 也需要额外的空间,并且在进行比较的时候,你的程序会变得更复杂
10、PreparedStatement
可以提升性能和安全
11、查询数据量大无缓冲查询
当使用脚本执行 SQL 语句的时候,程序会直到这个 SQL 语句有返回结果,然后才会往下继续执行,可以使用无缓冲查询来改变行为。尤其是那些会产生大量结果的查询,不需要等待所有结果返回,只需要第一行的数据返回的时候,就可以马上开始工作于查询结果了
12、把 IP 地址存成 UNSIGNED INT
使用一个无符号整形 UNSIGNED INT 来存放 IP,只需要四个字节 32 位存储
// 字符串 IP 转成整形
select INET_ATON('127.0.0.1') from dual;
// 整形转字符串 IP
select INET_NTOA('2130706433') from dual;
13、使用固定长度的表
固定长度的表会提高性能,因为MySQL搜寻的会更快一些,因为这些固定的长度是很容易计算下一个数据的偏移量的,所以读取的自然也会很快。而如果字段不是定长的,那么,每一次要找下一条的话,需要程序找到主键,但是定长字段会浪费一些空间,无论是否在使用,都要分配那么多的空间
14、垂直分割
将一个表中不常用的字段放在另一张表
15、拆分大的 DELETE 或 INSERT 语句
使用 limit 来限制
16、选择正确的存储引擎
对于查询非常频繁,使用 MYISAM 效率高一些,但是写入数据比较频繁的话,使用 InnoDB ,一般选用 InnoDB
存储在数据库目录中的一段声明性 SQL 语句
1、有助于提高应用程序的性能,存储过程编译之后,就存储在数据库中
2、有助于减少应用程序和数据库服务器之间的流量,应用程序不必发送多个冗长的 SQL 语句,而只能发送存储过程的名称和参数
3、存储的程序是安全的
1、使用大量存储过程,内存使用量会大大增加
2、存储过程的构造使得开发具有复杂业务逻辑的存储过程变得更加困难
3、很难调试存储过程
4、开发和维护存储过程不容易