MySQL优化

Posted Destiny,

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL优化相关的知识,希望对你有一定的参考价值。

 

 

如何实时查看mysql当前连接数?

 

1、查看当前所有连接的详细资料:

mysqladmin -uadmin -p -h10.140.1.1 processlist

 

 

2、只查看当前连接数(Threads就是连接数.):

mysqladmin  -uadmin -p -h10.140.1.1 status

 

 

 

 

mysql -u root --初始进入mysql

mysql -u root -p password --更改root用户进入MySQL的密码

修改之后以后登录输入:mysql -u root -p 

进入之后

SHOW MASTER LOGS; --查看当前数据库服务的日志文件信息

exit --退出MySQL

 

SHOW DATABASES; --查看当前服务器中有哪些库(默认建立了四个库:test mysql information_schema  performance_schema)

 

CREATE DATABASE Y2T55 DEFAULT CHARSET utf8 COLLATE utf8_general_ci;

--创建一个新库名为y2t55

 

USE y2t55 --引用库

CREATE TABLE XINXIBIAO (name char(20) not null, age int not null);--创建xinxibiao  之后是 名称 类型  不允许为空值

 

DESCRIBE y2t55.xinxibiao; --查看y2t55库里的xinxibiao的表结构

 

use y2t55

show tables --查看库里的表(先进入y2t55库里然后再查看表)

 

drop table y2t55.xinxibiao; --删除y2t55库里的xinxibiao

 

insert into xinxibiao values (‘zhangsan‘,20,);--将数据插入到成绩表里(以表的默认结构)

 

先引用库再查询表

use y2t55

select * from xinxibiao;--查询xinxibiao的内容

或者直接查询表

select * from y2t55.xinxibiao;

这是两种查询表内容的方法

 

查询特定的表内容:

select name,age from y2t55.xinxibiao;

查询某个人的内容:

select * from y2t55.xinxibiao where name=‘zhangsan‘;

 

update  y2t55.chengjibiao set  age=30  where name=‘lisi‘;--更改xinxibiao里的‘lisi’的age信息

更改完毕以后查看xinxibiao表: select * from y2t55.xinxibiao

 

delete from xinxibiao where name=‘zhangsan‘;--删除xinxibiao里zhangsan的信息(前提:必须要是在y2t55这个库里)

 

创建用户:

Create user ‘用户名’@’ip地址’ identified by ‘密码’;

删除用户:

Drop user ‘用户名’@’ip地址’;

修改用户:

Rename user ‘用户名’@’ip地址’; to ‘新用户名’@’新密码’;

修改密码:

Set password for ‘用户名’@’IP地址’ = password(‘新密码‘);

 

对于用户和IP的权限如下:

用户名@IP地址        用户只能在改IP下才能访问
用户名@192.168.1.%   用户只能在改IP段下才能访问(通配符%表示任意)
用户名@%             用户可以再任意IP下访问(默认IP地址为%)

 

1、查看权限:

show grants for ‘用户‘@‘IP地址‘

2、授权

grant  权限 on 数据库.表 to   ‘用户‘@‘IP地址‘

3、取消授权

revoke 权限 on 数据库.表 from ‘用户名‘@‘IP地址‘

授权实例如下:

grant all privileges on db1.tb1 TO ‘用户名‘@‘IP‘

grant select on db1.* TO ‘用户名‘@‘IP‘

grant select,insert on *.* TO ‘用户名‘@‘IP‘

revoke select on db1.tb1 from ‘用户名‘@‘IP‘

2、压缩备份


有时候,数据库的数据比较大,可能会用到压缩后进行备份,节省备份时间与磁盘空间的使用


[[email protected] ~]# mysqldump -uroot -p -B test|gzip >/download/testbak_$(date +%F).sql.gz

Enter password: 

[[email protected] ~]# ll /download/testbak_2016-12-12.sql.gz

-rw-r--r--. 1 root root 753 Dec 12 20:49 /download/testbak_2016-12-12.sql.gz

[[email protected] ~]# ll /download/

total 14

-rw-r--r--.  1 root root 2027 Dec 12 20:41 testbak_2016-12-12_b.sql

-rw-r--r--.  1 root root 1888 Dec 12 20:34 testbak_2016-12-12.sql

-rw-r--r--.  1 root root  753 Dec 12 20:49 testbak_2016-12-12.sql.gz


同时也可以看的压缩后的效果

多库备份:

[[email protected] ~]# mysqldump -uroot -p -B --events test mysql|gzip >/download/testbak_$(date +%F).sql02.gz

Enter password: 

[[email protected] ~]# ll /download/testbak_2016-12-12.sql02.gz                                  

-rw-r--r--. 1 root root 152749 Dec 12 20:54 /download/testbak_2016-12-12.sql02.gz

这样就不会有这为警告信息了

 

 

用户授权:

grant select on y2t55.* to ‘haha‘@‘localhost‘ identified by ‘123456‘;

      (权限)   (库.表名)  (用户名)(来源)    (设置密码)  --创建haha用户,对y2t55这个库里的所有表都有查看权限,来源来自于本地,用户密码为123456

 

权限--all代表所有权限

库.表名--*.*代表所有库.表

用户名--自己创建

来源--可以是域名、IP、‘%’代表通配符 192.168.3.% %.benet.com  表示来源地址可以是某个区域或者是某个网段

IDENTIFIED BY --设置密码  在identified by之后加密码   或者不输入identified by 说明授权的这个用户登录无需密码

 

查看权限

show grants for ‘haha‘@‘localhost‘;

                (用户)(来源本地)

查看结果:

| Grants for [email protected]                                                                                   |

+-------------------------------------------------------------------------------------------------------------+

| GRANT USAGE ON *.* TO ‘haha‘@‘localhost‘ IDENTIFIED BY PASSWORD ‘*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9‘ |

| GRANT SELECT ON `y2t55`.* TO ‘haha‘@‘localhost‘   

 

撤销权限

revoke select  on y2t55.* from ‘hehe‘@‘localhost‘;

       (权限)    (库.表)     (用户) (来源) --撤销hehe用户对y2t55库里的表的查看权限

 

权限:all代表所有

 

数据库备份:

方法1:导出指定库中的部分表

 mysqldump -u root -p mysql user > /root/mysql-user.sql --备份mysql库里的user表到/root/下名字叫做mysql-user.sql

 

方法2:导出一个或者多个完整的库(包括其中的表)

mysqldump -u root -p --databases mysql y2t55 > /root/mysql.y2t55.sql

                     (选项)    (库名)       ——备份mysql、y2t55这个两个库备份到、root下起名为mysql.y2t55.sql

 

方法三:备份mysql服务器中所有的库

mysqldump -u root -p  --opt --all-databases > /root/all.sql --备份MySQL服务器里的所有库到/root/下起名为all.sql

{选项}:--opt //优化执行速度

 

单表备份:

[[email protected] ~]# mysqldump -uroot -p -B test test >/download/test_testbak_$(date +%F).sql      

Enter password: 

[[email protected] ~]# egrep -v "#|^$|*" /download/test_testbak_2016-12-12.sql

-- MySQL dump 10.13  Distrib 5.5.52, for linux2.6 (x86_64)

 

分享一下民工哥,实际生产环境中一个简单的备份脚本,仅供参考

[[email protected] scripts]# vi bak.sh 

#!/bin/sh

##########################################

#this scripts create by root of mingongge

#create at 2016-11-11

#######################################

ip=`grep ‘IPADDR‘ /etc/sysconfig/network-scripts/ifcfg-eth0|awk -F "=" ‘{print $2}‘`

  #定义服务器IP变量

BAKDIR=/backup  

  #定义备份路径

[ ! -d $BAKDIR/${ip} ] && mkdir -p $BAKDIR/${ip}

 #判断如果不存在这个路径就创建一个,为了服务器多的时候方便看

DB_PWD="mingongge"

DB_USER="root"

MYSQL="/application/mysql/bin/mysql"

MYSQL_DUMP="/application/mysql/bin/mysqldump"

DATA=`date +%F`

####bak data of test‘s databses####

DB_NAME=`$MYSQL -u$DB_USER -p$DB_PWD -e "show databases;"|sed ‘1,5d‘`

  #定义数据库变量

for name in $DB_NAME

#for循环语句取库名

do

  $MYSQL_DUMP -u$DB_USER -p$DB_PWD -B ${name} |gzip >$BAKDIR/${ip}/${name}_$DATA.sql.gz  

 #全库备份

  [ ! -d $BAKDIR/${ip}/${name} ] && mkdir -p  $BAKDIR/${ip}/${name}

#判断这个路径,为了区别哪个库的备份文件

  for tablename in `$MYSQL -u$DB_USER -p$DB_PWD -e "show tables from ${name};"|sed ‘1d‘`

#for循环语句取表名

  do

   $MYSQL_DUMP -u$DB_USER -p$DB_PWD ${name} ${tablename} |gzip >$BAKDIR/${ip}/${name}/${tablename}_$DATA.sql.gz

#分表备份

  done

done


执行的结果如下

[[email protected] ~]# tree /backup/

/backup/

10.1xx.1xx.1xx   #服务器IP

  xxxxxxx           #其实是库名

      cash_balance_2016-12-15.sql.gz

      cash_depositor_2016-12-15.sql.gz

      cash_trade_2016-12-15.sql.gz

        crm_customer_2016-12-15.sql.gz

         crm_delivery_2016-12-15.sql.gz

        crm_order_2016-12-15.sql.gz

        crm_orderAction_2016-12-15.sql.gz

         crm_orderField_2016-12-15.sql.gz

       crm_plan_2016-12-15.sql.gz

 

恢复数据库

 

恢复整个库:

mysql -u root -p  < /root/y2.sql --将原先备份好的y2.sql 重定向导入到mysql服务器里

恢复某个库里的某个表:

mysqldump -u root -p y2t55 xinxibiao > /root/y2.x.sql ——先备份y2t55库里的xinxibiao 到/root/下起名为y2.x.sql

之后删除y2t55里的xinxibiao

然后恢复:

mysql -u root -p y2t55  < /root/y2.x.sql  ——将备份的y2.x.sql表恢复到y2t55库里

 

项目中,优化mysql之前,首先要开启慢查询日志,在分析慢查询日志.

数据库开启慢查询:

1,查看所有日志状态: show variables like ‘%quer%‘;
2,查看慢查询状态:show variables like ‘show%‘

Vim /etc/my.cnf

                       

#开启慢查询功能

slow_query_log = on

#慢查询日志存放路径与名称

slow_query_log_file = /usr/local/mysql/data/slow_query.log

#查询时间超时5s的查询语句

long_query_time = 5

#列出没有使用索引的查询语句

log-queries-not-using-indexes = on

 

 

操作系统配置优化

数据库是基于操作系统的,目前大多数mysql都是安装在Linux系统之上,所以对于操作系统的一些参数配置也会影响到mysql的性能,下面就列出一些常用到的系统配置;

 

网络方面配置需要修改/etc/sysct1.conf文件:

#增加TCP支持的队列数

net.ipv4.tcp_max_syn_backlog = 65535

#减少断开连接时,资源回收

net.ipv4.tcp_max_tw_buckets = 8000

net.ipv4.tcp_tw_reuse = 1

net.ipv4.tcp_tw_recycle =1

net.ipv4.tcp_fin_timeout = 10

 

操作系统配置优化:

打开文件数的限制,可以使用ulimit -a 查看目录的各位限制,可以修改/etc/security/limits.conf文件,增加以下内容以修改打开文件数量的限制。

*       soft    nofile  65535

*       hard    nofile  65535

除此之外最好在mysql服务器上关闭iptables,selinux等防火墙软件。

 

 

 

 

MySQL配置文件参数说明:

Vim  /etc/my.cnf

 

# Uncomment the following if you are using InnoDB tables

#innodb_data_home_dir = /usr/local/mysql/data

#innodb_data_file_path = ibdata1:10M:autoextend

#innodb_log_group_home_dir = /usr/local/mysql/data

# You can set .._buffer_pool_size up to 50 - 80 %

# of RAM but beware of setting memory usage too high

#innodb_buffer_pool_size = 16M[Ge1] 

#innodb_buffer_pool_instances [Ge2] 

#innodb_additional_mem_pool_size = 2M

# Set .._log_file_size to 25 % of buffer pool size

#innodb_log_file_size = 5M

#innodb_log_buffer_size = 8M[Ge3] 

#innodb_flush_log_at_trx_commit = 1[Ge4] 

#innodb_lock_wait_timeout = 50

#innodb_read_io_threads

#innodb_write_io_threads[Ge5] 

#innodb_stats_on_metadata[Ge6] 

 

 

服务器硬件优化

Disk IO优化

常用Raid级别简介;

Raid0:也称为条带,就是把多个磁盘链接成一个硬盘使用,这个级别IO最好。

Raid1:也称为镜像,要求至少有两个磁盘,魅族磁盘存储的数据相同。

Raid5:也是把多个(最少3个)硬盘合并成1个逻辑盘使用,数据读写是会建立奇偶校验信息,并且奇偶校验信息和相对应的数据分别存储于不同的磁盘上,当Raid5的一个磁盘数据发生损坏后,利用剩下的数据和相对应的奇偶校验信息去恢复被损坏的数据。

Raid1+0:就是Raid1和Raid0的组合,同时具备两个级别的优缺点,一般建议数据库使用这个级别。

 

 

一、Index索引

将Index放第一位,不用说,这种优化方式我们一直都在悄悄使用,那便是主键索引。有时候我们可能并不在意,如果定义适合的索引,数据库查询性能(速度)将提高几倍甚至几十倍。

普通索引

作用是提高查询速度。

建表,创建索引

CREATE TABLE tbl_name(

字段名称 字段类型 [完整性约束条件],

~

index [索引名] (column_name)

);

创建索引

CREATE INDEX index_name ON tab_name (column_name)

删除索引

DROP INDEX index_name FROM tab_name

查看索引

SHOW index FROM tab_name

主键索引

作用是加速查询和唯一约束

建表,创建索引

CREATE TABLE tbl_name(

字段名称 字段类型 [完整性约束条件],

~

PRIMARY KEY(column_name)

);

创建索引

ALTER TABLE tab_name ADD PRIMARY KEY(column_name)

删除索引

ALTER TABLE tab_name DROP PRIMAY KEY(column_name)

唯一索引

作用是加速查询和唯一约束

建表,创建索引

CREATE TABLE tbl_name(

字段名称 字段类型 [完整性约束条件],

~

unique [索引名] (column_name)

);

创建索引

CREATE UNIQUE INDEX index_name ON tab_name (column_name)

删除索引

DROP UNIQUE INDEX index_name FROM tab_name

二、少用SELECT*

可能有的人查询数据库时,遇到要查询的都会select,这是不恰当的行为。我们应该取我们要用的数据,而不是全取,因为当我们select时,会增加web服务器的负担,增加网络传输的负载,查询速度自然就下降 。

三、EXPLAIN SELECT

对于这个功能估计很多人都没见过,但是这里强烈推荐使用。explain显示了mysql如何使用索引来处理select语句以及连接表。可以帮助选择更好的索引和写出更优化的查询语句。主要用发就是在select前加上explain即可。

EXPLAIN SELECT [查找字段名] FROM tab_name ...

四、开启查询缓存

大多数的MySQL服务器都开启了查询缓存。这是提高性最有效的方法之一,而且这是被MySQL的数据库引擎处理的。当有很多相同的查询被执行了多次的时候,这些查询结果会被放到一个缓存中,这样,后续的相同的查询就不用操作表而直接访问缓存结果了。

第一步把query_cache_type设置为ON,然后查询系统变量have_query_cache是否可用:

show variables like ‘have_query_cache‘

之后,分配内存大小给查询缓存,控制缓存查询结果的最大值。相关操作在配置文件中进行修改。

五、使用NOT NULL

很多表都包含可为 NULL (空值) 的列,即使应用程序井不需要保存 NULL 也是如此 ,这是因为可为 NULL 是列的默认属性。通常情况下最好指定列为 NOT NULL,除非真 的需要存储 NULL 值。

如果查询中包含可为 NULL 的列,对 MySQL 来说更难优化 ,因为可为 NULL 的列使 得索引、索引统计和值比较都更复杂 。可为NULL 的列会使用更多的存储空间 ,在 MySQL 里也需要特殊处理 。当可为NULL 的列被索引肘,每个索引记录需要一个额 外的字节,在 MyISAM 里甚至还可能导致固定大小 的索引 (例如只有一个整数列的 索引) 变成可变大小的索引。

通常把可为 NULL 的列改为 NOT NULL 带来的性能提升比较小 ,所以 (调优时) 没有 必要首先在现有schema中查找井修改掉这种情况 ,除非确定这会导致问题。但是, 如果计划在列上建索引 ,就应该尽量避免设计成可为 NULL 的列。当然也有例外 ,例如值得一提的是,InnoDB 使用单独的位 (bit ) 存储 NULL 值 ,所 以对于稀疏数据由有很好的空间效率 。但这一点不适用于MyISAM 。

六、存储引擎的选择

对于如何选择MyISAM和InnoDB,如果你需要事务处理或是外键,那么InnoDB可能是比较好的方式。如果你需要全文索引,那么通常来说MyISAM是好的选择,因为这是系统内建的,然而,我们其实并不会经常地去测试两百万行记录。所以,就算是慢一点,我们可以通过使用Sphinx从InnoDB中获得全文索引。

数据的大小,是一个影响你选择什么样存储引擎的重要因素,大尺寸的数据集趋向于选择InnoDB方式,因为其支持事务处理和故障恢复。数据库的在小决定了故障恢复的时间长短,InnoDB可以利用事务日志进行数据恢复,这会比较快。而MyISAM可能会需要

几个小时甚至几天来干这些事,InnoDB只需要几分钟。

您操作数据库表的习惯可能也会是一个对性能影响很大的因素。比如: COUNT() 在 MyISAM表中会非常快,而在InnoDB表下可能会很痛苦。而主键查询则在InnoDB下会相当相当的快,但需要小心的是如果我们的主键太长了也会导致性能问题。大批的inserts语句在MyISAM下会快一些,但是updates在InnoDB 下会更快一些——尤其在并发量大的时候。

所以,到底你检使用哪一个呢?根据经验来看,如果是一些小型的应用或项目,那么MyISAM也许会更适合。当然,在大型的环境下使用MyISAM也会有很大成功的时候,但却不总是这样的。如果你正在计划使用一个超大数据量的项目,而且需要事务处理或外键支持,那么你真的应该直接使用InnoDB方式。但需要记住InnoDB的表需要更多的内存和存储,转换100GB的MyISAM 表到InnoDB 表可能会让你有非常坏的体验。

七、避免在 where 子句中使用 or 来连接

如果一个字段有索引,一个字段没有索引,将导致引擎放弃使用索引而进行全表扫描,如:

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

可以这样查询:

select id from t where num = 10
union all
select id from t where Name = ‘admin‘

八、多使用varchar/nvarchar

使用varchar/nvarchar代替 char/nchar ,因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。

九、避免大数据量返回

这里要考虑使用limit,来限制返回的数据量,如果每次返回大量自己不需要的数据,也会降低查询速度。

十、where子句优化

where 子句中使用参数,会导致全表扫描,因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。然 而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。

应尽量避免在 where 子句中对字段进行表达式操作,避免在where子句中对字段进行函数操作这将导致引擎放弃使用索引而进行全表扫描。不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。

 


 [Ge1]非常重要的一个参数,用于配置innodb的缓冲池如果数据库中只有Innodb表,则推荐配置量为总内存的75%

SELECT engine,ROUND(SUM(data_length+index_length)/1024/2014,1) AS "Total MB" FROM INFORMATION_SCHEMA.TABLES WHERE table_schema not in ("information_schema","performance_schema") GROUP BY ENGINE;

 

Innodb_buffer_pool_size >= Total MB

 [Ge2]可以控制缓冲池的个数,默认情况下只有一个缓冲池

 [Ge3]Innodb log缓冲的大小,由于日志最长每秒钟就会刷新所以一般不用太大

 [Ge4]关键参数,对innodb的IO效率影响很大,默认值为1,可以取0,1,2三个值,一般建议为2,但如果数据安全性要求比较高则使用默认值1

 [Ge5]这两个参数决定了Innodb读写IO进程数,默认为4

 [Ge6]决定了mysql在什么情况下会刷新innodb表的统计信息












以上是关于MySQL优化的主要内容,如果未能解决你的问题,请参考以下文章

如何优化C ++代码的以下片段 - 卷中的零交叉

从JVM的角度看JAVA代码--代码优化

部分代码片段

Android 逆向整体加固脱壳 ( DEX 优化流程分析 | DexPrepare.cpp 中 dvmOptimizeDexFile() 方法分析 | /bin/dexopt 源码分析 )(代码片段

linux中怎么查看mysql数据库版本

从mysql的片段中加载ListView