您的位置:首页 > 博客中心 > 数据库 >

Mysql优化方案

时间:2022-03-15 13:34

优化Mysql有几个方向?

  • 从sql语句入手
  • 考虑索引
  • 表结构的优化
  • 数据库(配置)

sql方面可以做什么优化?

 

  1.聚合函数的优化:

    对于max():在作用列上加索引

    对于count():也可以通过加索引增加sql的执行速度,但需要注意的是,count(列名)会屏蔽掉null值,而count(*)并不会;

 

  2.子查询优化:

    子查询通常性能低于连接查询,考虑将其改为连接查询:

      例子:

 

select title from film where film_id in (
    select film_id from actor where actor_id in (
        select actor_id from actor where name = ‘sandra‘));

 

        改为:

select a.title from film a join actor b
    on a.film_id = b.film_id
        where b = actor, name = ‘sandra‘;

 

  3.group by优化

    针对group by后底层使用的临时表和文件排序进行优化;

select actor.first, actor.last, count(*)
    from sakila.film_actor
        inner join sakila.actor using(actor_id)
            group by film.actor_id;

     存在使用临时表,文件排序;

select actor.first, acotor.last, c.cut
    from sakila.actor inner join (
        select actor_id, count(*) as cut
            from sakila.film_actor group by actor_id)
                as c using(actor_id);

  

  4.limit优化

select film_id, description
    from sakila.film
        order by title limit 50,5;

    存在耗性能的文件排序;

select film_id, description
    from sakila.film
        order by film_id limit 50,5;

    对有索引的列进行order by,省去了文件排序的消耗;

 

索引方面?

  1.在合适的列上建立索引

    where, group by, order by, on 等词缀常出现的列上建立索引;

 

  2.索引字段越小越好

    

  3.离散度越大的列,在联合索引越靠前

    离散度? 答:唯一值越多的列,离散度越好;

  

  4.删除冗余的索引

    如:主键上的索引(因为主键就是唯一索引)

      多个联合索引前缀列相同

      联合索引包含了主键索引

 

  TIP:安利一个查找冗余索引的语句:

 

SELECT a.table_schema AS ‘数据库‘, a.table_name AS ‘表名‘, a.index_name AS ‘索引1‘, b.index_name AS ‘索引2‘, a.column_name AS ‘重复列名‘
FROM information_schema.statistics a
    JOIN statistics b ON a.table_schema = b.table_schema
        AND a.table_name = b.table_name
        AND a.seq_in_index = b.seq_in_index
        AND a.column_name = b.column_name
WHERE a.seq_in_index = 1
    AND a.index_name != b.index_name

 

 

表结构的优化

  1.选择合适的数据类型

    能存下的最小的

    使用最简单的

    尽可能使用not null定义字段

    尽量少用text这种,非用不可最好分表

  

  2.用int来存放日期

create table test( id
    not AUTO_INCREMENT not null,
        timestr INT Primary key (id) );


INSERT into test(timestr)
    values ( UNIX_TIMESTAMP(‘2014-06-01 13:01:04‘) );



select FROM_UNIXTIME(time) from test;

 

  3.用bigint存放IP

create table sessions ( id int auto_increment
    not null, ipaddress, bigint, primary key(id) );

insert into sessions ( ipaddress
    values ( INET_ATON(‘192.168.0.1‘) );

select INET_NTOA ( ipaddress) from sessions;

 

 

范式化设计

  简单提一下范式:

    第一范式:有主键且非空不重复,单个列不可分;

    第二范式:满足第一范式的条件下,消除部分函数依赖;

    第三范式:满足第二范式的条件下,消除了传递依赖;

 

  反范式化:

    适当增加冗余的列,优化查询(空间换时间)

 

表的拆分

  表的垂直拆分:

    不常用的字段放入一个表中;

    大字段独立出去;

    经常使用的字段放一起;

  

  表的水平拆分:

    对id进行hash, mod(id, 5)

    不同id的存入不同的表中

 

数据库系统的优化

  1.linux 修改  /etc/sysctl.conf

    #增加tcp支持队列数

      net.ipv4.tcp_max_syn_backlig = 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

 

  2.打开文件数的限制

    ulimit -a查看目录限制

    修改文件 /etc/security/limits.conf

    写入 *soft nofile 65535

      *hard nofile 65535

    关闭 iptables, selinux 等防火墙(减少网络损耗)

 

  3.修改mysql的配置

    linux对应目录: /etc/my.conf 或 /etc/mysql/my.conf

    win对应目录: C://windows/my.ini

    

    重要参数的修改:

      innodb_buffer_pool_size = 75%* total RAM

      innodb_buffer_ poll_instances

      innodb_log_buffer_size                  (保证存下一秒钟的日志即可)

      innodb_flush_log_at_trx_commit    (默认是1,可以取0,1,2,表示多久将变更刷新至硬盘)

      innodb_read_io_threads                 (默认是4,引擎读io的线程数)

      innodb_write_io_threads      (默认是4,引擎写io的线程数)

      innodb_file_per_table                      (默认是off,控制引擎每个表使用的独立表空间)

      innodb_stats_on_metadata     (决定什么情况下刷新表的统计信息,设置为off就不会自动刷新了)

 

处理重复数据?

  原因:人为的重复录入,重复提交等;

  

  查询到重复数据:

    利用group by和having的组合:

select user, over, count(*)
    from user1 group by user
        having count(*) > 1;

  再删除即可

 

本类排行

今日推荐

热门手游