zoukankan      html  css  js  c++  java
  • Mysql规范和使用注意点(转)

    命名规范:

    1表名,字段名,索引名称使用小写字母,数字采用下划线进行分割

    2.表名采用模块名3个缩小字符 ‘前缀’之后顺序为表明

    3.表名,字段名不超过32个字符

    4.存储尸体数据的表,名称使用名词,单数

    5.索引 采用‘inx’开头

    6.不使用保留字

    7.存储实体表间多对多关系,名称建议采用‘noun_verb_noun’比如‘member_like_tag’

    在sql语句中保留字一律使用大写

    字符串使用单引号

    比如:

    SELECT id,title FROM xiaoqu WHERE id=1

    SELECT  id,title FROM xiaoqu  WHERE areacoe=’10002’;

    错误写法:

    -- 错误
    select ID, title from XiaoQu where id = 1
    SELECT id, title FROM xiaoqu WHERE areacode = "000100010001"

    关于表的设计

    默认使用innodb存储引擎

    字符集使用utf-8

    >charset 为‘utf-8’;校验规则 collation ‘utf_gereral_ci’

    效率优先,提示性能

    适当的牺牲范式,加入冗余

    会增加代码复杂度

    关于正确的使用时间类型:

    精确到秒 采用timestamp

    精确到时间 使用date

    一般不适用datetime

    每个表都应该含有插入时间和更新时间 这个字段

    不允许用字符串去存储时间

    字段尽量定义为not null

    给默认值 ‘’

    为什么要这样做的原因,进行查询的优化,可能这个字段会添加索引(为null情况下,会额外增加创建索引的开销) 含有null的复合索引无效

    类似于性别这样的固定状态的东西 优先使用enum和set

    enum占用一个字节,转为数值进行运算

    set视节点定,最多使用8个字节

    用好数值类型

    原则:适用就好,越小越好

    > TINYINT< SMALLINT < MEDIUMINT < INT < BIGINT
    >
    > 1 Byte/2 Bytes/3 Bytes/4 Bytes/8 Bytes

    > FLOAT(4B)/DOUBLE(8B)
    >
    > DECIMAL(M,D) (M+2 B)

    关于金钱这样经常参与运算的数据类型使用整形,不适用浮点数类型

    > 例如金额可以用分为单位,然后采用 `INT`。如果依然要以元为单位,可以采用 `DECIMAL`。

    数值类型和字符串类型进行比较

    数值类型的效率更高,查询更快速,占用空间小

    ### 使用 INT UNSIGNED 来存储 IPv4 地址

    > 使用 `INET_ATON` 将 IP 地址的字符串形式转换成数字形式;使用 `INET_NTOA` 将 IP 地址数字形式转换成字符串形式,以便查看。
    >
    > 当要查询某段的 IP 时,请参考以下示例:

    ### 不直接存储图片、音频、视频等大容量内容

    > 请使用分布式文件系统来存储图片、音频、视频等内容。数据库里只存储文件的位置。

    ### 少用并拆分TEXT/BLOB

    > TEXT类型处理性能远低于VARCHAR

    为什么尽量不要使用text/blob这样的字段

    强制生成硬盘临时表

    浪费空间

    varchar(65535)=>64K

    如需使用请拆分到独立的表进行存放;

    一张表中如果有很多的字段,是坏的设计

    请考虑io高效,表修复,alter快/高并发

    > 一个表有很多很多字段,是坏设计的味道。请再认真考虑设计是否正确。
    > IO高效/表修复快/Alter快/高并发
    > 以1G Size 500W Rows来评估
    >
    > - 顺序读取需N秒
    > - 单行不超过200Byte
    > - 单表不超50个INT字段,不超20个CHAR(10)字段
    > - 单表字段数上限控制在20-50个

    关于索引:

    合理的创建索引:

    索引的作用,优化查询

    减慢更新

    索引的添加综合评估数据的密度和数据的分布

    结合核心sql优先考虑覆盖索引

    ### 使用数字主键

    > 存储实体数据的表,其主键应该是数字类型。

    ### 不使用联合主键

    > 存储实体数据的表,不使用联合主键。
    > 存储实体表间多对多对应关系的表(仅有两个字段)允许例外。

    ### 不使用外键

    > 所有的表不建立外键约束。

    ### 联合索引字段数不超过 5 个

    > 一个联合索引的字段数太多,很可能是设计得不好,还很难符合命名的规范。

    ### 前缀索引长度不超过 8 个字符

    > 对字符串类型的字段建立索引,采用前缀索引,且长度不超过 8 个字符。

    ### 不使用负向查询

    > 负向查询是指,如果查询条件描述的是不要什么数据,其余的都要。例如 `!=`、`<>`、`NOT EXISTS`、`NOT IN` 以及 `NOT LIKE` 等就是负向查询,它们利用索引将会很辛苦。

    ### 一次查询的结果集不超过 100 行

    > 必要时使用 `LIMIT 100`

    ### LIMIT m, n,其中 m 应当小于 500

    > 使用 `SELECT ... LIMIT offset, row_count` 或者 `SELECT ... LIMIT row_count OFFSET offset` 时,当 offset 小于 500 时,允许使用。
    >

    sql
    -- 允许
    SELECT ... FROM property WHERE broker_id=? ORDER BY update_time LIMIT 40, 20
    -- 不允许
    SELECT ... FROM property WHERE areacode=? ORDER BY update_time LIMIT 4000, 20

    避免使用count()函数;

    > 能不使用就不使用,尽量用其他方法来解决。

    -- 正确
    SELECT 1 FROM propertys WHERE broker_id=? LIMIT 1

    -- 错误
    SELECT COUNT(*) FROM propertys WHERE broker_id=?

    在代码中可以通过获取size(),或者length获得长度

    ### 一次 COUNT() 可能扫描的行数应当确保小于 500 行

    > `COUNT()` 函数需要扫描所有的结果集之后才能得出结果。而结果集的大小需要业务知识来判断(`EXPLAIN` 方法只能来来检验某一个条件下的当前情况)。因此需要使用 `COUNT()` 查询的代码应当经过审阅。

    为什么使用count(*) 除非真的想统计nullable的字段;

    ### 不在索引列做运算
    > 不在索引列进行数学运算或函数运算
    > - 无法使用索引
    > - 导致全表扫描

    举例:
    root:xxx_db> select BrokerId from ajk_propertys where proid-100=101960636;
    1 row in set (5.11 sec)

    尽量不要再数据库上做运算

    复杂的sql运算转移到程序端cpu

    简单实用mysql

    ### 同数据类型的列值比较
    > 原则:数字对数字,字符对字符
    > 字符列与数值类型比较
    > 数值列于字符列比较
    > - 同时转换为双精度进行比较
    > 字符列于数值列比较
    > - 字符列整列转数值,不会使用索引

    sql

    -- 禁止
     
    SELECT id FROM property WHERE NOW() - update_time < 3600
     
    SELECT id FROM property WHERE update_time + 3600 > NOW()

    -- 改为
     
    SELECT id FROM property WHERE update_time > NOW() - 3600

    sql
     
      -- 禁止
     
    SELECT id FROM property WHERE CHAR_LENGTH(title) > 20

    sql
     
    -- 假设字段 property.status 的类型为 TINYINT
     
    -- 禁止
     
    SELECT id FROM property WHERE status = '1'

    -- 改为
     
    SELECT id FROM property WHERE status = 1

    ### 禁止隐式类型转换

    > 不仅在查询条件中禁止隐示类型转换,`INSERT`,`UPDATE` 也不允许隐式类型转换。

    ```
    sql
    -- 假设字段 property.status 的类型为 TINYINT
    -- 禁止
    INSERT INTO property (..., status) VALUES (..., '1')
    UPDATE property SET status = '1' WHERE id = '43'

    -- 改为
    INSERT INTO property (..., status) VALUES (..., 1)
    UPDATE property SET status = 1 WHERE id = 43

    ### 禁止使用 % 前导查询

    > 尽量不使用 `LIKE` 查询,不得不用的情况下也禁止使用 `%` 前导查询。
    > - 使用不了索引
    > - 导致全表扫描

    ### 禁止SQL语句拼接
    > 应用程序不能有拼接语句出现

    拒绝3B

    大sql(拆分)

    大事物 (contrller 不适用事物,在service层开启)

    大批量(使用load data)

    > 大SQL VS 多个简单SQL
    >
    > - 传统设计思想,BUT Mysql NOT
    > - 一条SQL只能在一个CPU运算
    > - 1000+ QPS的高并发中,1秒大SQL可能把数据库都堵死

    > 拒绝大SQL,拆解成多条简单SQL
    > - 简单SQL缓存命中率更高
    > - 减少锁表时间,特别是MYISAM
    > - 用上多CPU

    > 不同字段,将or改为union
    > - 减少对不同字段进行 or 查询
    > - Merge index 往往很弱智

    保持事物连接尽量短小

    即开即用,用完就关

    减少锁资源占用

    不破坏一致性的前提小,使用多个短事物代替长事物;

    > 统一字符集为UTF8
    > 禁用子查询
    > - 大部分情况优化较差
    > - 特别是Where中使用IN id的子查询
    > - 一般可用JOIN改写

    ### 约定类规范(二)
    > 永远不在程序端显示加锁
    > - 永远不在程序端对数据库显式加锁
    > - 外部锁对数据库不可控
    > - 高并发是灾难
    > - 极难调试和排查
    > 可采用事务操作

    ```
    举例:
    Select GET_LOCK(‘str’)
    ```
    ### 约定类规范(三)
    > 请不要使用存储过程
    > 请不要使用trigger

  • 相关阅读:
    漫话性能:USE方法
    MIPI 屏参调试
    Linux下访问匿名页发生的神奇“化学反应”
    USB 2.0 suspend resume
    谈谈Linux内核驱动的coding style
    Apollo ROS原理(一)
    BMS(电池管理系统)第五课 ——核心!!!SOH算法开发
    蓝牙核心技术概述(一)蓝牙概述
    BMS(电池管理系统)第三课 ——BMS功能清单和采样要求
    登录密码加密vue版(转载)
  • 原文地址:https://www.cnblogs.com/xu-xiang/p/5983903.html
Copyright © 2011-2022 走看看