zoukankan      html  css  js  c++  java
  • 转载&修改:赶集mysql军规

    个人认为以下军规主要为了适应海量数据场景,对于业务复杂性系统并一定完全按照此军规
     
    一,核心军规
    • 不在数据库做计算,cpu计算务必移至业务层
    • 控制单表数据量,单表记录控制在千万级
    • 控制列数量,字段数控制在20以内
    • 平衡范式与冗余,为提高效率可以牺牲范式设计,冗余数据
    • 拒绝3B(big),大sql,大事务,大批量
     
    二,字段类军规
    • 用好数值类型
    tinyint(1Byte)
    smallint(2Byte)
    mediumint(3Byte)
    int(4Byte)
    bigint(8Byte)
    bad case:int(1)/int(11)
    bigint
    从 -2^63 (-9223372036854775808) 到 2^63-1 (9223372036854775807) 的整型数据(所有数字)。存储大小为 8 个字节。
    int
    从 -2^31 (-2,147,483,648) 到 2^31 - 1 (2,147,483,647) 的整型数据(所有数字)。存储大小为 4 个字节。int 的 SQL-92 同义字为 integer。
    smallint
    从 -2^15 (-32,768) 到 2^15 - 1 (32,767) 的整型数据。存储大小为 2 个字节。
    tinyint
    从 0 到 255 的整型数据。存储大小为 1 字节。
     
    • 有些字符转化为数字
    用int而不是char(15)存储ip
    • 优先使用enum或set
    例如:`sex` enum (‘F’, ‘M’) ;ENUM保存的是TINYINT
    • 避免使用NULL字段
    NULL字段很难查询优化
    NULL字段的索引需要额外空间
    NULL字段的复合索引无效
    bad case:
    `name` char(32) default null
    `age` int not null
    good case:
    `age` int not null default 0
    • 不在数据库里存图片
     
    三,索引类军规
    • 谨慎合理使用索引
    改善查询、减慢更新
    索引一定不是越多越好(能不加就不加,要加的一定得加)
    覆盖记录条数过多不适合建索引,例如“性别” ;添加区分度高的索引能过滤掉80%的数据
    • 字符字段必须建前缀索引
    • 不在索引做列运算
    -bad case:
    select id where age +1 = 10;
    -good case:
    $curDate = date('Y-m-d'); $res = mysql_query('select * from order where date < = $curDate');
    • innodb主键合理使用自增列
    主键建立聚簇索引
    主键不应该被修改
    字符串不应该做主键
    如果不指定主键,innodb会使用唯一且非空值索引代替
    • 不用外键,请由程序保证约束
     
    四,sql类军规
    • sql语句尽可能简单
    一条sql只能在一个cpu运算
    大语句拆小语句,减少锁时间
    一条大sql可以堵死整个库
    • 简单的事务
    事务时间尽可能短
    bad case:
    上传图片事务
    • 避免使用触发器,用户自定义函数,请由程序取而代之
    • 前导模糊查询不能使用索引
    bad case:
    select * from order where desc like '%XX'
    good case:
    select * from order where desc like 'XX%'
    • 避免使用not或!= 使用in替代,如果序列是连续的话使用between
    • 区分in和exists, not in和not exists
    select * from 表A where id in (select id from 表B)
    上面sql语句相当于
    select * from 表A where exists(select * from 表B where 表B.id=表A.id)
    区分in和exists主要是造成了驱动顺序的改变(这是性能变化的关键),如果是exists,那么以外层表为驱动表,先被访问,如果是IN,那么先执行子查询。所以IN适合于外表大而内表小的情况;EXISTS适合于外表小而内表大的情况。
    关于not in和not exists,推荐使用not exists,不仅仅是效率问题,not in可能存在逻辑问题。如何高效的写出一个替代not exists的sql语句?
    原sql语句
    select colname … from A表 where a.id not in (select b.id from B表)
    高效的sql语句
    select colname … from A表 Left join B表 on where a.id = b.id where b.id is null
     
    • 如果明确知道只有一条结果返回,使用limit 1
    • 不用select *
    消耗cpu,io,内存,带宽
    这种程序不具有扩展性
    • limit高效分页
    limit越大,效率越低
    select id from t limit 10000, 10;
    应该改为 =>
    select id from t where id > 10000 limit 10;
     
    • 使用union all替代union,union有去重开销
    • 尽量不用连接join
    • 务必请使用“同类型”进行比较,否则可能全表扫面
    bad case :
    select * from user where phone=13800001234
    -使用varchar(20)存储手机号,解读:
    a)涉及到区号或者国家代号,可能出现+-()
    b)varchar可以支持模糊查询,例如:like“138%”
     
    • 如果业务大部分是单条查询,使用Hash索引性能更好,例如用户中心
    select * from user where uid=? select * from user where login_name=?
    原因:
    B-Tree索引的时间复杂度是O(log(n))
    Hash索引的时间复杂度是O(1)
     
    • 打散批量更新
    • 使用性能分析工具
    show profile;
    mysqlsla;
    mysqldumpslow;
    show slow log;
    show processlist;
    show query_response_time(percona)
    explain;
     EXPLAIN 查看SQL执行计划。
    下面来个简单的示例,标注(1,2,3,4,5)我们要重点关注的数据
     
      1. type列,连接类型。一个好的sql语句至少要达到range级别。杜绝出现all级别
      2. key列,使用到的索引名。如果没有选择索引,值是NULL。可以采取强制索引方式
      3. key_len列,索引长度
      4. rows列,扫描行数。该值是个预估值
      5. extra列,详细说明。注意常见的不太友好的值有:Using filesort, Using temporary
     

  • 相关阅读:
    关于'for' loop initial declaration used outside C99 mode的说明
    Qt编写安防视频监控系统50-地图配置
    当封装已成为往事
    关于Qt数据库相关开发的一些经验总结
    Qt编写安防视频监控系统49-多数据库支持
    Qt编写安防视频监控系统48-视频参数
    设计测试用例优点和缺点
    常用的七种性能测试方法
    测试资料学习网站推荐
    打印$_SERVER['REQUEST_SCHEME']为空
  • 原文地址:https://www.cnblogs.com/dxf813/p/8126417.html
Copyright © 2011-2022 走看看