Mysql 优化方案

Mysql 优化方案

运行状态查询

了解mysql数据库的一些运行状态如何查询(比如想知道当前mysql运行的时间/一共执行了多少次select/update/delete.. / 当前连接)

show [seesion| gloable] status like ….
如:
//查询运行时间
show status like ‘uptime’;
//select | insert |delete 语句执行次数
show status like ‘com_select’
show status like ‘com_insert’
show status like ‘com_delete’
// 查询链接次数
show status like ‘connections’
// 查询慢查询语句
show status like 'slow_queries';
//默认慢查询时间10秒
show variables like ‘long_query_time’;
set long_query_time=1 ;//可以修改慢查询时间
// 慢查询设置my.ini
log-slow-queries = D:/Mysql/mysql-5.6.27-winx64/slowquery.log
long_query_time = 2

字段优化

尽量使用TINYINT、SMALLINT、MEDIUM_INT作为整数类型而非INT,如果非负则加上UNSIGNED
VARCHAR的长度只分配真正需要的空间
尽量使用TIMESTAMP而非DATETIME,
单表不要有太多字段,建议在20以内
避免使用NULL字段,很难查询优化且占用额外索引空间 default ”
用整型来存IP

索引使用优化

  1. 查询是否使用索引 关键字:explain select …
  2. like 避免使用 %key(前匹配)
  3. 避免使or,适当用in 代替
  4. 字段类型为字符串 必须用” 引起来,否则索引失效
  5. group by colm 默认会排序,建议使用 后面加order by null
  6. 能用链接的不用子查询
  7. 避免在where 子句中使用is null 判断 可以使用is not null
  8. 值很少的字段不适合建立索引
  9. 字符字段最好不要做主键
  10. 使用多列索引时主意顺序和查询条件保持一致,同时删除不必要的单列索引
  11. 强制使用某索引 select * from table force index(indexname)或use
  12. 前缀索引,当字段长度超过255需要定义截取 255
  13. 索引是表达式或函数的参数,索引被破坏
  14. 避免where 子句使用 != 和<> ,索引被破坏
  15. 对于连续数字,使用between a and b 代替 in

补充:索引使用定位

id

        查询顺序标识
            如:mysql> explain select * from (select nid,name from tb1 where nid < 10) as B;
            +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
            | id | select_type | table      | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
            +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
            |  1 | PRIMARY     | <derived2> | ALL   | NULL          | NULL    | NULL    | NULL |    9 | NULL        |
            |  2 | DERIVED     | tb1        | range | PRIMARY       | PRIMARY | 8       | NULL |    9 | Using where |
            +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
        特别的:如果使用union连接气值可能为null

select_type

        查询类型
            SIMPLE          简单查询
            PRIMARY         最外层查询
            SUBQUERY        映射为子查询
            DERIVED         子查询
            UNION           联合
            UNION RESULT    使用联合的结果
            ...
table

        正在访问的表名

type

    查询时的访问方式,性能:all < index < range < index_merge < ref_or_null < ref < eq_ref < system/const
    ALL   全表扫描,对于数据表从头到尾找一遍
            select * from tb1;
            特别的:如果有limit限制,则找到之后就不在继续向下扫描
                select * from tb1 where email = 'seven@live.com'
                select * from tb1 where email = 'seven@live.com' limit 1;
                虽然上述两个语句都会进行全表扫描,第二句使用了limit,则找到一个后就不再继续扫描。

    INDEX  全索引扫描,对索引从头到尾找一遍
           select nid from tb1;

    RANGE  对索引列进行范围查找
           select *  from tb1 where name < 'alex';
           PS:
             between and
             in
             >   >=  <   <=  操作
             注意:!= 和 > 符号

    INDEX_MERGE 合并索引,使用多个单列索引搜索
                select *  from tb1 where name = 'alex' or nid in (11,22,33);

    REF   根据索引查找一个或多个值
          select *  from tb1 where name = 'seven';

    EQ_REF  连接时使用primary key 或 unique类型
            select tb2.nid,tb1.name from tb2 left join tb1 on tb2.nid = tb1.nid;

    CONST  常量
           表最多有一个匹配行,因为仅有一行,在这行的列值可被优化器剩余部分认为是常数,const表很快,因为它们只读取一次。
           select nid from tb1 where nid = 2 ;

    SYSTEM 系统
           表仅有一行(=系统表)。这是const联接类型的一个特例。
           select * from (select nid from tb1 where nid = 1) as A;

possible_keys

        可能使用的索引

key

        真实使用的

key_len

        MySQL中使用索引字节长度

rows

        mysql估计为了找到所需的行而要读取的行数 ------ 只是预估值

extra

        该列包含MySQL解决查询的详细信息
        “Using index”
            此值表示mysql将使用覆盖索引,以避免访问表。不要把覆盖索引和index访问类型弄混了。
        “Using where”
            这意味着mysql服务器将在存储引擎检索行后再进行过滤,许多where条件里涉及索引中的列,当(并且如果)它读取索引时,就能被存储引擎检验,因此不是所有带where子句的查询都会显示“Using where”。有时“Using where”的出现就是一个暗示:查询可受益于不同的索引。
        “Using temporary”
            这意味着mysql在对查询结果排序时会使用一个临时表。
        “Using filesort”
            这意味着mysql会对结果使用一个外部索引排序,而不是按索引次序从表里读取行。mysql有两种文件排序算法,这两种排序方式都可以在内存或者磁盘上完成,explain不会告诉你mysql将使用哪一种文件排序,也不会告诉你排序会在内存里还是磁盘上完成。
        “Range checked for each record(index map: N)”

分表优化

` 数据大 且访问量大 建议使用分表(也可以联合搭配分区)

除非单表数据未来会一直不断上涨,否则不考虑拆分,拆分会带来 逻辑部署等复杂问题,分表和表分区的目的就是减少数据库的负担,提高数据库的效率,通常点来讲就是提高表的增删改查效率。

分表的特点:
1. 将一个大表按一定规则分解成多张具有 独立的存储空间实体子表
2. 独立的数据文件、索引文件、表结构文件
3. 可以分布到不同机器、磁盘上
4. 按照规则访问定义好的子表

使用: 分表需要创建表,使用和维护比较麻烦

分区

访问量不大,但是数据量大建议使用分区
1. 分区的好处是:
表面看还是一张表,是将数据分段存储到多个位置
访问还是一张表
分区表的数据更容易维护,可以通过清楚整个分区批量删除大量数据,也可以增加新的分区来支持新插入的数据。另外,还可以对一个独立分区进行优化、检查、修复等操作
部分查询能够从查询条件确定只落在少数分区上,速度会很快
分区表的数据还可以分布在不同的物理设备上
可以使用分区表赖避免某些特殊瓶颈,例如InnoDB单个索引的互斥访问、ext3文件系统的inode锁竞争
可以备份和恢复单个分区

四种分区 使用方法:
查询是否支持分区:SHOW VARIABLES LIKE ‘%partition%’;
1. Range 分区

-- 创建分区
DROP TABLE IF EXISTS t_range_text;
CREATE TABLE t_range_text(
   id INT(64) NOT NULL auto_increment ,
   `name` VARCHAR(64) NOT NULL DEFAULT '',
   -- 这里需要设置为datatime 不能设置timesimple
   createTime datetime NOT NULL,
   -- 分区的字段需要建立索引
   primary KEY(id,`createTime`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8  
PARTITION BY RANGE (year(createTime))
(
    PARTITION 2000_year VALUES less than(2000),
    PARTITION 2005_year VALUES less than(2005),
    PARTITION 2010_year VALUES less than(2010),
    PARTITION 2015_year VALUES less than(2015),
    PARTITION other_year VALUES less than MAXVALUE
);
-- 查看PARTITIONS字段是否使用分区
EXPLAIN PARTITIONS  SELECT * FROM t_range_text;

-- 删除数据或者删除分区
ALTER TABLE t_range_text DROP PARTITION 2000_year; 

-- 增加分区(有maxvalue分区无法加,且只范围参数只能变大不能变小)
ALTER TABLE t_range_text ADD PARTITION (PARTITION 2000_year VALUES LESS THAN (2000)); 

-- 合并分区
ALTER TABLE t_range_text
REORGANIZE PARTITION 2005_year,2010_year,2015_year  INTO
(
PARTITION 2015_year VALUES LESS THAN (2015)
)

2 . LIST 分区

CREATE TABLE t_list_text(  
    id INT NOT NULL,  
    fname VARCHAR(30),   
    store_id INT  
)   
PARTITION BY LIST(store_id)  
    PARTITION one VALUES IN (3,5,6,9,17),  
    PARTITION two VALUES IN (1,2,10,11,19,20),  
    PARTITION three VALUES IN (4,12,13,14,18),  
    PARTITION fore VALUES IN (7,8,15,16)  
);

-- 插入数据需注意 store_id 必须在列表中
insert into t_list_text values(1,'11',33);X

3 HASH分区

CREATE TABLE employees (  
    id INT NOT NULL,  
    fname VARCHAR(30),   
    store_id INT  
)  
PARTITION BY HASH(store_id)  
PARTITIONS 4;

-- PARTITION BY LINER HASH(store_id) 线性hash是2的幂运算(普通的是取模运算)
-- 优点:在于增加、删除、合并和拆分分区将变得更加快捷
-- 缺点:常规HASH分区得到的数据分布相比,各个分区间数据的分布不大可能均衡。

5 key 分区

create table t_key( 
  a int(11), 
  b datetime
) 
partition by key (b) 
partitions 4;

-- PARTITION BY LINER key(store_id) 线性hash是2的幂运算(普通的是取)
-- 优点:在于增加、删除、合并和拆分分区将变得更加快捷
-- 缺点:常规HASH分区得到的数据分布相比,各个分区间数据的分布不大可能均衡。

读写分离

主-从读写分离在该文章中实现:
http://blog.csdn.net/u012442381/article/details/77141781

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值