第一部分:SQL语句优化

1、尽量避免使用select *,使用具体的字段代替*,只返回使用到的字段。

2、尽量避免使用in 和not in,会导致数据库引擎放弃索引进行全表扫描。

SELECT * FROM t WHERE id IN (2,3)SELECT * FROM t1 WHERE username IN (SELECT username FROM t2)

优化方式:如果是连续数值,可以用between代替。如下:

SELECT * FROM t WHERE id BETWEEN 2 AND 3

如果是子查询,可以用exists代替。如下:

SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t2 WHERE t1.username = t2.username)

3、尽量避免在字段开头模糊查询,会导致数据库引擎放弃索引进行全表扫描。如下:

SELECT * FROM t WHERE username LIKE '%li%'

优化方式:尽量在字段后面使用模糊查询。如下:

SELECT * FROM t WHERE username LIKE 'li%'

4、尽量避免进行null值的判断,会导致数据库引擎放弃索引进行全表扫描。如下:

SELECT * FROM t WHERE score IS NULL

优化方式:可以给字段添加默认值0,对0值进行判断。如下:

SELECT * FROM t WHERE score = 0

5、尽量避免在where条件中等号的左侧进行表达式、函数操作,会导致数据库引擎放弃索引进行全表扫描。如下:

SELECT * FROM t2 WHERE score/10 = 9SELECT * FROM t2 WHERE SUBSTR(username,1,2) = 'li'

优化方式:可以将表达式、函数操作移动到等号右侧。如下:

SELECT * FROM t2 WHERE score = 10*9SELECT * FROM t2 WHERE username LIKE 'li%'

6.当只要一行数据时使用LIMIT 1

加上LIMIT 1可以增加性能。MySQL数据库引擎会在查找到一条数据后停止搜索,而不是继续往后查询下一条符合条件的数据记录

7、使用连接(JOIN)来代替子查询(Sub-Queries)

8、在建有索引的字段上尽量不要使用函数进行操作

例如,在一个DATE类型的字段上使用YEAE()函数时,将会使索引不能发挥应有的作用。

9、排序的索引问题

mysql查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序,如果需要最好给这些列创建复合索引。

10、应尽量避免在 where 子句中使用 != 或 <> 操作符,否则将引擎放弃使用索引而进行全表扫描。

11、应尽量避免在 where 子句中使用 or 来连接条件,如果一个字段有索引,一个字段没有索引,将导致引擎放弃使用索引而进行全表扫描,如:

select id from t where num=10 or Name = 'admin'

可以这样查询:

select id from t where num = 10union allselect id from t where Name = 'admin'

12、索引应建立在那些将用于JOIN,WHERE判断和ORDERBY排序的字段上。尽量不要对数据库中某个含有大量重复的值的字段建立索引。

比如性别可能就只有两个值,建索引不仅没什么优势,还会影响到更新速度,这被称为过度索引。

第二部分:数据库索引

1、索引的创建、查看、删除

//创建索引有两种方式:1.CREATE TABLE语句时可以创建索引   2.单独用CREATE INDEX或ALTER TABLE来为表增加索引// 1、ALTER TABLE 用来创建普通索引、唯一索引、主键索引和全文索引ALTER TABLE table_name ADD INDEX index_name (column_list);ALTER TABLE table_name ADD UNIQUE (column_list);ALTER TABLE table_name ADD PRIMARY KEY (column_list);ALTER TABLE table_name ADD FULLTEXT (column_list);// 2、CREATE INDEX可对表增加普通索引或UNIQUE索引以及全文索引,但是不可以对表增加主键索引CREATE INDEX index_name ON table_name (column_list);CREATE UNIQUE index_name ON table_name (column_list);CREATE FULLTEXT index_name ON table_name (column_list);
查看索引mysql> show index from tblname;mysql> show keys from tblname;
删除索引删除索引的mysql格式 :DORP INDEX IndexName ON tab_name;

2、使用索引的优缺点

创建索引可以大大提高系统的性能, 可以大大加快数据的检索速度。

索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有 必要。

第一,   创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。第二,   索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。第三,   当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。

一般来说,应该在这些列上创建索引。第一,   在经常需要搜索的列上,可以加快搜索的速度;第二,   在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构;第三,   在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度;第四,   在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的;第五,   在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;第六,   在经常使用在WHERE子句中的列上面创建索引,加快条件的判断速度。

一般来说,不应该创建索引的的这些列具有下列特点:第一,在查询中很少使用列不应该创建索引。第二,对于只有很少数据值的列也不应该增加索引。这是因为,由于这些列的取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。第三,对于那些定义为text, image和bit数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少。第四,当修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改性能远远大于检索性能时,不应该创建索引。

3、组合索引

组合索引的生效原则是  从前往后依次使用生效,如果中间某个索引没有使用,那么断点前面的索引部分起作用,断点后面的索引没有起作用;

造成断点的原因:

前边的任意一个索引没有参与查询,后边的全部不生效。

前边的任意一个索引字段参与的是范围查询,后面的不会生效。

断点跟索引字字段在SQL语句中的位置前后无关,只与是否存在有关。

where a=3 and b=45 and c=5 .... #这种三个索引顺序使用中间没有断点,全部发挥作用;where a=3 and c=5... #这种情况下b就是断点,a发挥了效果,c没有效果where b=3 and c=4... #这种情况下a就是断点,在a后面的索引都没有发挥作用,这种写法联合索引没有发挥任何效果;where b=45 and a=3 and c=5 .... #这个跟第一个一样,全部发挥作用,abc只要用上了就行,跟写的顺序无关

(a,b,c) 三个列上加了联合索引(是联合索引 不是在每个列上单独加索引)而是建立了a,(a,b),(a,b,c)三个索引,另外(a,b,c)多列索引和 (a,c,b)是不一样的。

(0) select * from mytable where a=3 and b=5 and c=4;#abc三个索引都在where条件里面用到了,而且都发挥了作用(1) select * from mytable where  c=4 and b=6 and a=3;#这条语句为了说明 组合索引与在SQL中的位置先后无关,where里面的条件顺序在查询之前会被mysql自动优化,效果跟上一句一样(2) select * from mytable where a=3 and c=7;#a用到索引,b没有用,所以c是没有用到索引效果的(3) select * from mytable where a=3 and b>7 and c=3;#a用到了,b也用到了,c没有用到,这个地方b是范围值,也算断点,只不过自身用到了索引(4) select * from mytable where b=3 and c=4;#因为a索引没有使用,所以这里 bc都没有用上索引效果(5) select * from mytable where a>4 and b=7 and c=9;#a用到了  b没有使用,c没有使用(a使用的是范围查询)(6) select * from mytable where a=3 order by b;#a用到了索引,b在结果排序中也用到了索引的效果,前面说了,a下面任意一段的b是排好序的(7) select * from mytable where a=3 order by c;#a用到了索引,但是这个地方c没有发挥排序效果,因为中间断点了,使用 explain 可以看到 filesort(8) select * from mytable where b=3 order by a;#b没有用到索引,排序中a也没有发挥索引效果

在查询时,MYSQL只能使用一个索引,如果建立的是多个单列的普通索引,在查询时会根据查询的索引字段,从中选择一个限制最严格的单例索引进行查询。别的索引都不会生效。

第三部分:MySQL优化:explain分析

Explain是Mysql的自带查询优化器,负责select语句的优化器模块,可以模拟优化器执行SQL查询语句,从而知道Mysql是如何处理SQL的,语法也很简单:Explain + SQL

1、id:反映的是表的读取的顺序,或查询中执行select子句的顺序。

小表永远驱动大表,三种情况:

(1)id相同,执行顺序是由上至下的

(2)id不同,如果是子查询,id序号会递增,id值越大优先级越高,越先被执行

(3)id存在相同的,也存在不同的,所有组中,id越大越先执行,如果id相同的,从上往下顺序执行

  

  derived是衍生虚表的意思,derived2中的2对应id2

2、select_type:反映的是Mysql理解的查询类型

(1)simple:简单的select查询,查询中不包含子查询或union。

(2)primary:查询中若包含任何复杂的字部分,最外层查询标记为primary。

(3)subquery:select或where列表中的子查询。

(4)derived(衍生):在from列表中包含的子查询,Mysql会递归执行这些子查询,把结果放在临时表里。

(5)union:若第二个select出现在union后,则被标记为union,若union包含在from字句的子查询中,外层select将被标记为derived

(6)union result:union后的结果集

3、table:反映这一行数据是关于哪张表的

4、type:访问类型排序

反映sql优化的状态,至少达到range级别,最好能达到ref

查询效率:system > const > eq_ref > ref > range > index > all

  (完整的排序:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index >all)  

(1)system:从单表只查出一行记录(等于系统表),这是const类型的特例,一般不会出现

(2)const:查询条件用到了常量,通过索引一次就找到,常在使用primary key或unique索引中出现。

   

  where id=1写死,所以类型是const

(3)eq_ref:唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配,常见于主键或唯一索引扫描。

(4)ref:非唯一性索引扫描,返回匹配某个单独值的所有行,本质上也是一种索引访问,它可能会找到多个符合条件的行,与eq_ref的差别是eq_ref只匹配了一条记录。

(5)range:只检索给定范围的行,使用一个索引来选择行。key列显示使用了哪个索引,一般是在where语句中出现了between、、in等的查询。

  这种范围扫描索引扫描比全表扫描要好,因为它只需要开始于索引的某一点,而结束于另一点,不用扫描全部索引。与eq_ref和ref的区别在于筛选条件不是固定值,是范围。

  

(6)index:full Index scan,index和all的区别为index类型只遍历索引树。这通常比all快,因为索引文件通常比数据文件小。

  

  要获得的id信息,刚好id在索引上,从索引中读取

  (all和index都是读全表,但index是从索引中读取的,而all是从硬盘中读的)

(7)all:全表扫描,如果查询数据量很大时,全表扫描效率是很低的。

5、possible_keys、key、key_len:反映实际用到了哪个索引,索引是否失效

(1)possible_keys:Mysql推测可能用到的索引有哪些,但不一定被查询实际使用

(2)key:实际使用的索引,若为null,则可能没建索引或索引失效。

   

  (查询中若使用了覆盖索引,则该索引仅出现在key列表中。

  覆盖索引:select后面的字段和所建索引的个数、顺序一致)

(3)key_len:表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度。同样的查询结果下,长度越短越好。

  key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的。

6、ref:反映哪些列或常量被用于查找索引列上的值

  

7、rows:根据表统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数

  

  仅通过主键索引查找是641行

  

  建完相关的复合索引再查,需要查询的行数就变少了

8、Extra

(1)using filesort:mysql中无法利用索引完成的排序,这时会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取。

   

  创建索引时就会对数据先进行排序,出现using filesort一般是因为order by后的条件导致索引失效,最好进行优化。

  

  order by的排序最好和所建索引的顺序和个数一致

(2)using temporary:使用了临时表保存中间结果,mysql在对查询结果排序时使用临时表。常见于排序order by和分组查询group by。

   

  影响更大,所以要么不建索引,要么group by的顺序要和索引一致

  

(3)using index:表示相应的select操作中使用了覆盖索引,避免访问了表的数据行,效率好

  覆盖索引:select后的数据列只从索引就能取得,不必读取数据行,且与所建索引的个数(查询列小于等于索引个数)、顺序一致。

  所以如果要用覆盖索引,就要注意select的列只取需要用到的列,不用select *,同时如果将所有字段一起做索引会导致索引文件过大,性能会下降。

  

  出现using where,表明索引被用来执行索引键值的查找

  

  如果没有同时出现using where,表明索引用来读取数据而非执行查找动作。

(4)using where:表明使用了where过滤

(5)using join buffer:使用了连接缓存

(6)impossible where:where子句的值是false

(7)select tables optimized away

(8)distinct:优化distinct操作,在找到第一匹配的元组后即停止找同样值的动作

第四部分:数据库性能优化

一方面可以单台运行多个MySQL实例让服务器性能发挥到最大化,另一方面是对数据库进行优化,往往操作系统和数据库默认配置都比较保守,会对数据库发挥有一定限制,可对这些配置进行适当的调整。

4.1 数据库配置优化

MySQL常用有两种存储引擎,一个是MyISAM,不支持事务处理,读性能处理快,表级别锁。另一个是InnoDB,支持事务处理(ACID),设计目标是为处理大容量数据发挥最大化性能,行级别锁。

表锁:开销小,锁定粒度大,发生死锁概率高,相对并发也低。

行锁:开销大,锁定粒度小,发生死锁概率低,相对并发也高。

使用InnoDB存储引擎是最好的选择。

InnoDB参数默认值:

innodb_buffer_pool_size = 128M#索引和数据缓冲区大小,一般设置物理内存的60%-70%innodb_buffer_pool_instances = 1    #缓冲池实例个数,推荐设置4个或8个innodb_flush_log_at_trx_commit = 1  #关键参数,0代表大约每秒写入到日志并同步到磁盘,数据库故障会丢失1秒左右事务数据。1为每执行一条SQL后写入到日志并同步到磁盘,I/O开销大,执行完SQL要等待日志读写,效率低。2代表只把日志写入到系统缓存区,再每秒同步到磁盘,效率很高,如果服务器故障,才会丢失事务数据。对数据安全性要求不是很高的推荐设置2,性能高,修改后效果明显。innodb_file_per_table = OFF  #默认是共享表空间,共享表空间idbdata文件不断增大,影响一定的I/O性能。推荐开启独立表空间模式,每个表的索引和数据都存在自己独立的表空间中,可以实现单表在不同数据库中移动。innodb_log_buffer_size = 8M#日志缓冲区大小,由于日志最长每秒钟刷新一次,所以一般不用超过16M

4.2 系统内核优化

大多数MySQL都部署在linux系统上,所以操作系统的一些参数也会影响到MySQL性能,以下对linux内核进行适当优化。

net.ipv4.tcp_fin_timeout = 30#TIME_WAIT超时时间,默认是60snet.ipv4.tcp_tw_reuse = 1    #1表示开启复用,允许TIME_WAIT socket重新用于新的TCP连接,0表示关闭net.ipv4.tcp_tw_recycle = 1  #1表示开启TIME_WAIT socket快速回收,0表示关闭net.ipv4.tcp_max_tw_buckets = 4096   #系统保持TIME_WAIT socket最大数量,如果超出这个数,系统将随机清除一些TIME_WAIT并打印警告信息net.ipv4.tcp_max_syn_backlog = 4096#进入SYN队列最大长度,加大队列长度可容纳更多的等待连接

在linux系统中,如果进程打开的文件句柄数量超过系统默认值1024,就会提示“too many files open”信息,所以要调整打开文件句柄限制。

# vi /etc/security/limits.conf  #加入以下配置,*代表所有用户,也可以指定用户,重启系统生效* soft nofile 65535* hard nofile 65535# ulimit -SHn 65535   #立刻生效

4.3 硬件配置

加大物理内存,提高文件系统性能。linux内核会从内存中分配出缓存区(系统缓存和数据缓存)来存放热数据,通过文件系统延迟写入机制,等满足条件时(如缓存区大小到达一定百分比或者执行sync命令)才会同步到磁盘。也就是说物理内存越大,分配缓存区越大,缓存数据越多。当然,服务器故障会丢失一定的缓存数据。

SSD硬盘代替SAS硬盘,将RAID级别调整为RAID1+0,相对于RAID1和RAID5有更好的读写性能(IOPS),毕竟数据库的压力主要来自磁盘I/O方面。

第五部分:数据库架构扩展

5.1 主从复制

分为同步复制和异步复制,实际复制架构中大部分为异步复制。复制的基本过程如下:

1)Slave上面的IO进程连接上Master,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容;

2)Master接收到来自Slave的IO进程的请求后,通过负责复制的IO进程根据请求信息读取制定日志指定位置之后的日志信息,返回给Slave 的IO进程。返回信息中除了日志所包含的信息之外,还包括本次返回的信息已经到Master端的bin-log文件的名称以及bin-log的位置;

3)Slave的IO进程接收到信息后,将接收到的日志内容依次添加到Slave端的relay-log文件的最末端,并将读取到的Master端的 bin-log的文件名和位置记录到master-info文件中,以便在下一次读取的时候能够清楚的告诉Master“我需要从某个bin-log的哪个位置开始往后的日志内容,请发给我”;

4)Slave的Sql进程检测到relay-log中新增加了内容后,会马上解析relay-log的内容成为在Master端真实执行时候的那些可执行的内容,并在自身执行。

主要搭建配置步骤:

    (1)修改master,slave服务器

  1. master服务器配置:vi /usr/local/mysql/etc/my.cnf[mysqld]server-id=202     #设置服务器唯一的id,默认是1,我们设置ip最后一段,slave设置203log-bin=mysql-bin # 启用二进制日志#binlog-ignore-db = mysql,information_schema  #忽略写入binlog的库
    
    slave服务器配置:vi /usr/local/mysql/etc/my.cnf[mysqld]server-id=203replicate-do-db = abc     #只同步abc库slave-skip-errors = all   #忽略因复制出现的所有错误

    (2)在主服务器上建立帐户并授权slave

mysql> mysql -u root -p123.commysql> GRANT REPLICATION SLAVE ON *.* to ‘sync’@‘192.168.1.2’ identified by ‘1234.com’; #replication:复制

    (3)配置从数据库

mysql> change master to -> master_host='192.168.0.202', -> master_user='sync', -> master_password='1234.com', -> master_log_file='mysql-bin.000002', -> master_log_pos=263;#Log和pos是master上随机获取的。这段也可以写到my.cnf里面。

    (4)启动slave同步进程并查看状态

mysql> start slave;

    

其中Slave_IO_Running 与 Slave_SQL_Running 的值都必须为YES,才表明状态正常。

  (5)查看主数据库状态

mysql> show master status;+------------------+----------+--------------+------------------+| File  | Position | Binlog_Do_DB | Binlog_Ignore_DB |+------------------+----------+--------------+------------------+| mysql-bin.000002 | 263 |  |   |+------------------+----------+--------------+------------------+

(6)验证主从同步

在主mysql创建数据库abc,再从mysql查看已经同步成功。

5.2  MySQL Proxy 实现读写分离

大多数企业是在代码层面实现读写分离,另一个种方式通过代理程序实现读写分离,常见代理程序有MySQL Proxy、Amoeba。在这样数据库集群架构中,大大增加数据库高并发能力,解决单台性能瓶颈问题。如果从数据库一台从库能处理2000 QPS,那么5台就能处理1w QPS。

基本原理是让主数据库处理写方面事务,让从库处理SELECT查询。

主服务器Master:192.168.0.202

从服务器Slave:192.168.0.203

调度服务器MySQL-Proxy:192.168.0.204

(1)安装mysql-proxy

    下载:http://dev.mysql.com/downloads/mysql-proxy/

(2)配置mysql-proxy,创建主配置文件

cd /usr/local/mysql-proxymkdir lua #创建脚本存放目录mkdir logs #创建日志目录cp share/doc/mysql-proxy/rw-splitting.lua ./lua #复制读写分离配置文件cp share/doc/mysql-proxy/admin-sql.lua ./lua #复制管理脚本vi /etc/mysql-proxy.cnf   #创建配置文件[mysql-proxy]user=root #运行mysql-proxy用户admin-username=proxy #主从mysql共有的用户admin-password=123.com #用户的密码proxy-address=192.168.0.204:4000 #mysql-proxy运行ip和端口,不加端口,默认4040proxy-read-only-backend-addresses=192.168.0.203 #指定后端从slave读取数据proxy-backend-addresses=192.168.0.202 #指定后端主master写入数据proxy-lua-script=/usr/local/mysql-proxy/lua/rw-splitting.lua #指定读写分离配置文件位置admin-lua-script=/usr/local/mysql-proxy/lua/admin-sql.lua #指定管理脚本log-file=/usr/local/mysql-proxy/logs/mysql-proxy.log #日志位置log-level=info #定义log日志级别,由高到低分别有(error|warning|info|message|debug)daemon=true    #以守护进程方式运行keepalive=true #mysql-proxy崩溃时,尝试重启保存退出!chmod 660 /etc/mysql-porxy.cnf

(3)修改读写分离配置文件

vi /usr/local/mysql-proxy/lua/rw-splitting.luaif not proxy.global.config.rwsplit then proxy.global.config.rwsplit = {  min_idle_connections = 4, #默认超过4个连接数时,才开始读写分离  max_idle_connections = 8, #默认8  is_debug = false }end

(4)启动mysql-proxy

/usr/local/mysql-proxy/bin/mysql-proxy --defaults-file=/etc/mysql-proxy.cnfnetstat -tupln | grep 4000 #已经启动tcp 0 0 192.168.0.204:4000 0.0.0.0:* LISTEN 1264/mysql-proxy关闭mysql-proxy使用:killall -9 mysql-proxy

(5)在主服务器创建proxy用户用于mysql-proxy使用,从服务器也会同步这个操作

mysql> grant all on *.* to 'proxy'@'192.168.0.204' identified by '123.com';

(6)测试读写分离

使用客户端连接mysql-proxy

mysql -u proxy -h 192.168.0.204 -P 4000 -p123.com

5.3 MySQL-MMM 实现主主复制

有时,面对大量写操作的应用时,单台写性能达不到业务需求。如果做双主,就会遇到数据库数据不一致现象,产生这个原因是在应用程序不同的用户会有可能操作两台数据库,同时的更新操作造成两台数据库数据库数据发生冲突或者不一致。在单库时MySQL利用存储引擎机制表锁和行锁来保证数据完整性,怎样在多台主库时解决这个问题呢?有一套基于perl语言开发的主从复制管理工具,叫MySQL-MMM(Master-Master replication managerfor Mysql,Mysql主主复制管理器),这个工具最大的优点是在同一时间只提供一台数据库写操作,有效保证数据一致性。

mmm_mond:监控进程,负责所有的监控工作,决定和处理所有节点角色活动。此脚本需要在监管机上运行。

mmm_agentd:运行在每个mysql服务器上的代理进程,完成监控的探针工作和执行简单的远端服务设置。此脚本需要在被监管机上运行。

mmm_control:一个简单的脚本,提供管理mmm_mond进程的命令。

mysql-mmm的监管端会提供多个虚拟IP(VIP),包括一个可写VIP,多个可读VIP,通过监管的管理,这些IP会绑定在可用mysql之上,当某一台mysql宕机时,监管会将VIP迁移至其他mysql。

在整个监管过程中,需要在mysql中添加相关授权用户,以便让mysql可以支持监理机的维护。授权的用户包括一个mmm_monitor用户和一个mmm_agent用户,如果想使用mmm的备份工具则还要添加一个mmm_tools用户。

5.4 增加缓存

 给数据库增加缓存系统,把热数据缓存到内存中,如果缓存中有要请求的数据就不再去数据库中返回结果,提高读性能。缓存实现有本地缓存和分布式缓存,本地缓存是将数据缓存到本地服务器内存中或者文件中。分布式缓存可以缓存海量数据,扩展性好,主流的分布式缓存系统有memcached、redis,memcached性能稳定,数据缓存在内存中,速度很快,QPS可达8w左右。如果想数据持久化就选择用redis,性能不低于memcached。

5.5 分库

分库是根据业务不同把相关的表切分到不同的数据库中,比如web、bbs、blog等库。如果业务量很大,还可将切分后的库做主从架构,进一步避免单个库压力过大。

5.6 分表

数据量的日剧增加,数据库中某个表有几百万条数据,导致查询和插入耗时太长,怎么能解决单表压力呢?你就该考虑是否把这个表拆分成多个小表,来减轻单个表的压力,提高处理效率,此方式称为分表。

分表技术比较麻烦,要修改程序代码里的SQL语句,还要手动去创建其他表,也可以用merge存储引擎实现分表,相对简单许多。分表后,程序是对一个总表进行操作,这个总表不存放数据,只有一些分表的关系,以及更新数据的方式,总表会根据不同的查询,将压力分到不同的小表上,因此提高并发能力和磁盘I/O性能。

分表分为垂直拆分和水平拆分:

垂直拆分:把原来的一个很多字段的表拆分多个表,解决表的宽度问题。你可以把不常用的字段单独放到一个表中,也可以把大字段独立放一个表中,或者把关联密切的字段放一个表中。

水平拆分:把原来一个表拆分成多个表,每个表的结构都一样,解决单表数据量大的问题。

第六部分:开启慢查询日志

一旦开启慢日志查询会增加数据库的压力。

mysql> set global slow-query-log=on  #开启慢查询功能mysql> set global slow_query_log_file='/var/log/mysql/mysql-slow.log';  #指定慢查询日志文件位置mysql> set global log_queries_not_using_indexes=on;   #记录没有使用索引的查询mysql> set global long_query_time=1;   #只记录处理时间1s以上的慢查询

第七部分:数据库备份

insert into select 优化_数据库优化总结相关推荐

  1. Android 性能优化之数据库优化(一)

    Android性能优化系列汇总已完成,包括: Android 性能优化实例 Android 性能优化之数据库优化(一) Android 性能优化之布局优化 (二) Android 性能优化之Java( ...

  2. zabbix mysql优化 my.cnf_zabbix数据库优化之数据库优化(二)

    zabbix数据库优化之数据库优化二 简介 数据库history设置是保存7天.然后如果你没有分区.虽然数据在减少但是表空间不会减少.浪费硬盘空间的同事缓存内的cache部分也没有被释放.分区后可以迁 ...

  3. oracle的优化适用于mysql吗_性能优化之数据库优化,适用于Sqlite、Mysql、Oracle、Sql server,详细介绍了索引和事务及部分针对Sqlite的优化...

    本文为性能优化的第一篇--数据库性能优化,原理适用于大部分数据库包括Sqlite.Mysql.Oracle.Sql server,详细介绍了索引(优缺点.分类.场景.规则)和事务,最后介绍了部分单独针 ...

  4. mysql做十亿条数据查询_数据库优化:mysql数据库单机数十亿数据查询设计

    很久没写文章,是不是想着写点什么东西,分享下我的数据库设计思路,主要是针对单机数十亿及以上数据查询优化技巧. 如果只是简单的查询,没有频繁的写入操作,对查询速度不要求在毫秒级别,就不需要什么大型的数据 ...

  5. 物联网 mysql数据库优化_MySQL数据库优化大全方法汇总-阿里云开发者社区

    随着数据和负载增加,MySQL数据库会日渐缓慢,性能越来越差,用户体验也随之变差,所以数据库性能优化十分紧迫,云吞铺子分享MySQL数据库优化大全: MySQL数据库优化 云吞铺子先模拟一下数据库访问 ...

  6. mysql悲观锁优化_MySQL数据库优化(三)—MySQL悲观锁和乐观锁(并发控制)

    一.悲观锁 1.排它锁,当事务在操作数据时把这部分数据进行锁定,直到操作完毕后再解锁,其他事务操作才可操作该部分数据.这将防止其他进程读取或修改表中的数据. 2.实现:大多数情况下依靠数据库的锁机制实 ...

  7. table 条数过大优化_MySQL 数据库优化,看这篇就够了 | 不长不短,2000 字小结

    前言 数据库优化一方面是找出系统的瓶颈,提高MySQL数据库的整体性能,而另一方面需要合理的结构设计和参数调整,以提高用户的相应速度,同时还要尽可能的节约系统资源,以便让系统提供更大的负荷. 1. 优 ...

  8. oracle去重差个数,多表查询 - Oracle 查询技巧与优化_数据库技术_Linux公社-Linux系统门户网站...

    前言 上一篇blog介绍了Oracle中的单表查询和排序的相关技巧,本篇blog继续介绍查询中用的最多的--多表查询的技巧与优化方式,下面依旧通过一次例子看一个最简单的多表查询. 多表查询 上一篇中提 ...

  9. 性能优化之数据库优化

    原文出处:http://www.trinea.cn/android/database-performance/ 1.索引 简单的说,索引就像书本的目录,目录可以快速找到所在页数,数据库中索引可以帮助快 ...

最新文章

  1. Intellij IDEA eclipse项目导入
  2. 八个非常实用的vsCode扩展插件,千万别错过了!
  3. linux的svn同步文件在哪里,linux svn服务器同步文件在哪里
  4. 阿里巴巴将赴NIPS 2017 3大事业部联袂展示AI全技能
  5. JS 客户端浏览器操作、BOM、渗透客户端浏览器(windows对象:screen屏幕操作、location浏览器域名、history浏览器历史、Navigator浏览器信息、cookie)
  6. ajax onload怎么用,Ajax中onload和onreadystatechange两种请求方式的区别
  7. 创建应答文件——无人值守安装XP/2003
  8. itextpdf 加密解密
  9. Invest模型-碳储量计算
  10. python丨Scrapy框架案例二:阳光问政平台
  11. java 控制系统音量_用JNI实现调节win7系统音量
  12. 液晶12864(KS0108主控)
  13. 计算机硬盘使用率测试软件,测试硬盘速度的10款软件
  14. 人工智能作用现代认知战探析
  15. Nginx多个域名配置ssl证书出错解决方案
  16. python 自动化测试(2):针对密码输入框为密码控件时的解决方案
  17. Android中实现红绿灯动画,android红绿灯制作
  18. 工程力学(17)—应力状态和强度理论
  19. 学计算机要数学和英语怎么说,高中数学和英语有点恼火。但本人大学想学计算机,就是不知道英语和数学与计算机专业有什么必要联络吗?...
  20. MySQL数据库实操教程(15)——表的关联关系

热门文章

  1. 无法生成部件汇总表_RFID在汽车零部件企业仓储物流中的应用
  2. Shiro并发登录人数控制遇到的问题和解决
  3. oracle sum详解,oracle sum()聚合函数
  4. c语言添加变量到数据库+a+ +b+ 的方法,《C程序设计基础》模拟考试题(含答案)...
  5. 大橙子_橙子皮养花太棒了,酸性大,肥力足,比花肥强10倍
  6. python列表是顺序表还是链表_顺序表与链表
  7. k1658停运_最新通知!福州这些列车停运!
  8. java pair class,在Java Pair Class Tuple中获取值
  9. 钉钉一个人怎么多部门 钉钉一个人加入多个部门的技巧
  10. 腾讯视频上传视频如何同步到企鹅号