zoukankan      html  css  js  c++  java
  • DB-MySQL:MySQL 语句性能优化

    ylbtech-DB-MySQL:MySQL 语句性能优化
    1.返回顶部
    1、

    MySQL概述
    1.数据库设计 3范式
    2.数据库分表分库---会员系统() 水平分割(分页如何查询)MyChar 、垂直
    3.怎么定位慢查询
    ---------------------
    数据库索引的优化、索引原理
    SQL语句调优
    数据库读写分离--MyChar
    ---------------------
    分组 having
    存储过程、触发器、函数
    存储过程:写了一块sql语句,类似Java中方法,只需调用传参数,弊端:sql语句是写死的,不好灵活改变。
    mysql(免费、开源)oracle(收费)
    mysql 分页 limit 。oracle:rownum 伪列


    MySQL优化方案
    1.数据库设计要合理(3F)
    2.添加索引(普通索引、主键索引、唯一索引、全文索引)底层:B-Tree和B+Tree 和二叉树算法一样,减少全表扫描
    3.分表分库技术(取模分表、水平分割、垂直分割)
    4.读写分离
    5.存储过程
    6.配置MySQL最大连接数 my.ini
    7.mysql服务器升级
    8.随时清理碎片化
    9.sql语句调优 核心


    数据库三大范式
    数据库设计
    什么是数据设计(减少冗余量、3F)
    什么事数据库3范式
    1F 原子约束 表示每列不可再分
       id  name     sex   address
      1   zhangsan  0    北京

      是否保证原子(看业务)

    2F 保证唯一,主键
       id orderNum(唯一) name     sex   address
      1  123              zhangsan  0    北京
      订单表中,是否用id作为订单号?不允许。
      项目内部rpc远程调用 大多数是使用id进行通讯的,给外部看的是orderNum,保证系统安全性。
     
      分布式系统解决并发生成订单号
      怎么保证抢票中,订单号不会重复生成?怎么保证订单的幂等性(幂等就是不重复)?
      提前将订单号生成号,存在redis中,需要是直接去redis中去取;分布式锁

    3F 不要有冗余数据  classId  className重复,这个表只存classId即可
       id  name     sex   address  classId  className
      1   zhangsan  0    北京     1        一班
      2   lisi    0    北京     2        二班
      2   wangwu   0    北京     1        一班

      从新建张表:
     classId  className
     1        一班
     2        二班
     
     注意:不一定完全要遵循第3F。


    MySQL分库分表
    什么时候分库:
        电商项目当中,将一个项目拆分,拆分成多个小项目,每个小的项目有自己单独的数据库,互不影响。--垂直分割。
      会员数据库、订单数据库、支付数据库

    什么时候分表:
        水平分割,分表规则,根据业务需求。存放日志 根据年分表、手机号 根据前三位分表 136 135 135
      水平分割(取模算法)

      user表  分成三张表 
      id  name   address
      1   张三   北京
      2   李四   北京
      3   王五   北京
      4   赵六   北京
      5   小明   北京
      6   小红   北京

      怎样将6条数据存放在三张不同的表中,怎样非常均匀? 取模算法
      表: user0 user1 user2  
      第一条数据:1%3=1 ,放user1表。  
      第二条数据:2%3=2 ,放user2 表。   
      第三条数据:3%3=0 ,放user0表。依次类推

      实现取模分表算法:三张表id不能自动增长,需要专门有一张表存放userId,给赋值过去。


    水平分割取摸算法案例
    好处:非常均匀的分配
    怎样查在哪里表?找id为6在哪个表 6%3=0 在user0表找

    Demo:

    create table uuid(
     id int unsinged primary key auto_increment,
    )engine=myisam charset utf8;

    @Service
    public class UserService{
     
     @Autowired
     private JdbcTemplate jdbcTemplate;

      /**
      * 生成用户信息
      */
     public String regit(String name,String pwd){
      //1.生成userId
      String insertUuidSql="insert into uuid values (null)";
      // 这里一般用直接返回主键id,不用下面的查询
        jdbcTemplate.update(insertUuidSql);
      //select last_insert_id()表示查询最近的主键ID的意思
        Long userId = jdbcTemplate.queryForObject("select last_insert_id()",requiredType,Long.class);
      //2.存放具体哪张表中
      String tableName = "user"+userId%3;
      //3插入到具体表中
      String insertUserSql = "insert into "+tableName+" values("+userId+","+userName+","+pwd+")";
      System.out.println(insertUserSql);
      jdbcTemplate.update(insertUserSql);
      return "success";
     }

     /**
      * 根据id查询
      */
     public String get(Long userId){
      //1.存放具体哪张表中
      String tableName = "user"+userId%3;
      String selectUserSql="select name from "+tableName+"where id="+userId;
      String name = jdbcTemplate.queryForObject(selectUserSql,String.class);
      return name;
     }
    }

    @RestController
    public class UserController{

     @Autowired
     private UserService userService;

     @RequestMapping("/regit")
     public String regit(String name,String pwd){
       return userService.regit(name,pwd);
     }

     @RequestMapping("/getUser")
     public String get(Long userId){
       return userService.get(userId);
     }
    }

    @SpringBootApplication
    public class App{
     public static void main(String[] args) {
         SpringApplication.run(App.class,args);
      }
    }

    分表之后有什么缺点?
    1.怎么分页查询
    2.查询非常受限制,例如查性别男要查三张表
    3.取模算法 如果表发生改变了,表要重新分,打乱了 使用阿里云RDS数据库

    先主表存放所有数据 ,根据业务需求进行分表


    如何定位慢查询

    什么是慢查询?
    MySQL默认慢查询是10秒,如果10秒没有响应回来就是慢查询,一般在生产环境设置为1秒

    慢查询都会有日志存放
    show status 命令

    如何修改慢查询
    --查询慢查询次数
    show status like 'slow_queries';
    --查询慢查询时间
    show variables like 'long_query_time';
    --修改慢查询时间
    set long_query_time=1; 表示修改慢查询时间为1秒

    如何将慢查询定位到日志中
    在默认情况下,MySQL不会记录慢查询,需要在启动MySQL的时候,指定记录慢查询才可以。

    编辑配置文件/etc/my.cnf加入如下内容
    [mysqld]
    slow_query_log = ON
    slow_query_log_file = /var/lib/mysql/test-10-226-slow.log
    long_query_time = 1

    修改配置后重启mysql
    systemctl restart mysqld
    mysql -uroot -p

    MySQL索引概述

    为什么要索引?提高查询效率
    为什么索引能够提高查询效率--索引实现原理 折半查找

    索引分类:
    主键索引 -- primary key
    添加主键索引方式:
    1. 创建表的时候添加:id int unsinged primary key auto_increment,
    2. 如果创建表的时候没有添加:alert table 表名 add primary key (列名);

    删除主键索引:alert table 表名 drop primary key;

    C:ProgramDataMySQLMySQL Server 5.6data est 下:

    *.frm 表结构文件
    *.MYD 数据结构文件
    *.MYI 索引文件

    唯一索引
    组合索引
    全文索引
    普通索引


    索引底层实现原理

    索引底层采用b-tree 折半查找又叫二分查找

    没有索引是全表扫描--索引 减少全表扫描

    索引 b-tree 首先生成索引文件

    索引有什么缺点?增加、删除 索引文件也需要更新

    普通索引与唯一索引

    唯一索引:关键字unique
    create table 表名称(
     id int primary key auto_increment, // 主键索引
     name varchar(32) unique;      //唯一索引
    )

    注意:unique字段可以为null,并可以有多个null,但是如果有具体内容,则不能重复。
    唯一索引用的不多,被主键索引代替了。


    普通索引:
    create table 表名(
     id int unsigned,
     name varchar(32)
    )

    创建普通索引:creat index 索引名 on 表 (列1,列2);

    creat index index_aaa on aaa (name);

    --执行计划 查看有没有使用索引
    explain select * from aaa where name="zhangsan";
    查询出type为ref表示使用索引 all是全表扫描

    全文索引:

    create table aaa(
     id int primary key,
     title varchar(200),
     body TEXT,
     FULLTEXT(title,body)  // 创建全文索引
    )engine = innodb;


    模糊查询:select * from aaa where body like '%张%' ; 错误用法,索引不会生效

    使用执行计划查看是否使用索引:
    explain select * from aaa where body like '%张%' ;

    使用索引查询: select * from aaa where match(title,body) against('张')

    使用执行计划查看是否使用索引:
    explain select * from aaa where match(title,body) against('张')

    使用全文索引的时候:
    不要like
    企业实际中不会采用表的全文索引。全文索引有非常大的缺点,InnoDB(数据库存储引擎)中不支持全文索引

     
    SQL语句优化方案总结

    索引优缺点:
    优点:提高程序效率
    缺点:增加、删除慢,索引文件需要更新,增加内存

    什么字段适合加索引?
    查询次数比较多,值有非常多的不同

    建立索引场景:
    建立索引的时候,where条件需要查询的,并且值非常多的不同的。唯一几个值(sex:0,1),不需要建立索引。


    索引注意事项,sql调优部分:


    --创建主键索引
    alert talbe 表名 add primary key (列名);
    --创建组合索引文件
    alert table 表名 add index my_ind(列1,列2);

    注意:
    1.对于创建的多列索引,如果不使用第一部分,则不会创建索引
    explain select * from 表名 where 列1 = 'aaa';  -- 使用索引
    explain select * from 表名 where 列2 = 'bbb';  -- 使用全表扫描

    2.使用索引的时候,不要使用like'%%' ,这样会全表扫描,使用like,开头不要%
    explain select * from 表名 where 列1 like '%aaa%';  -- 使用全表扫描
    explain select * from 表名 where 列1 like 'aaa%';   -- 使用索引

    3.使用or,条件都必须加索引,只要有一个条件不加索引,就会全表扫描
    explain select * from 表名 where 列1 = 'aaa' or 列3 ='ccc';  -- 使用索引

    4.判断是否为null ,使用is null 不要=null
    5.使用group by 分组不会采用索引,会全表扫描
    explain select * from 表名 group by 列2;
    6.分组需要效率高,禁止排序(分组默认排序)
    explain select * from 表名 group by 列2 order by null ;
    7. select * from aaa where userId>=100 和 select * from aaa where userId>100 哪个效率高
    不要使用大于等于,会判断两次全表扫描

    8. in和not in 加上索引后也不会使用索引,能用between就不要用in
    9.查询量非常大时,采用缓存、分表、分页

    MySQL存储引擎区别

    MySQL存储引擎:innodb/ myisam/ memory

    主流:innodb 支持事务机制

    innodb与myisam区别:
    批量添加--myisam效率高
    innodb--事务机制非常安全

    锁机制:
    myisam是表锁
    innodb是行锁,不会影响整个表

    数据结构:
    myisam 支持全文检索,一般不用数据库自带的全文检索。

    都支持b-tree数据结构

    索引缓存 都支持。

    Myisam注意事项

    创建myisam引擎表结构:
    create table ccc(id int,name varchar(32))engine=myisam;
    添加数据:
    insert into ccc values(1,'a');
    insert into ccc values(2,'b');
    insert into ccc values(3,'b');
    insert into ccc select id,name from ccc;

    删除id为3的所有数据
    delete from ccc where id = 3;

    会发现:ccc.MYD文件大小没有改变,缺点:没有真正的删除,删除后能够非常快的恢复过来

    真要删除使用:optimize table ccc; 表示对myisam进行整理,清了碎片化。
    企业实际中是不会物理删除数据的,数据迁移

    2、
    2.返回顶部
     
    3.返回顶部
     
    4.返回顶部
     
    5.返回顶部
     
     
    6.返回顶部
     
    warn 作者:ylbtech
    出处:http://ylbtech.cnblogs.com/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    STM32学习之路-SysTick的应用(时间延迟)
    STM32M CUBE实现printf打印调试信息以及实现单字节接收
    iframe动态创建及释放内存
    第13周项目2-成绩处理
    1036. Boys vs Girls (25)
    CS0433: 类型“BasePage”同一时候存在于“c:WindowsMicrosoft.NETxxxxxxxxxxxxxxxx
    Java读取Excel转换成JSON字符串进而转换成Java对象
    Java对象与JSON互相转换jsonlib以及手动创建JSON对象与数组——(二)
    GSON中Java对象与JSON互相转换——(一)
    Java泛型方法与泛型类的使用------------(五)
  • 原文地址:https://www.cnblogs.com/storebook/p/10150425.html
Copyright © 2011-2022 走看看