zoukankan      html  css  js  c++  java
  • MySQL从表设计到查询优化

    一、为什么要优化
        1. 系统的吞吐量瓶颈往往出现在数据库的访问速度上
        2. 随着应用程序的运行,数据库的中的数据会越来越多,处理时间会相应变慢
        3. 数据是存放在磁盘上的,读写速度无法和内存相比
     
     
    二、如何优化
        1. 设计数据库时:数据库表、字段的设计,存储引擎
        2. 利用好MySQL自身提供的功能,如索引等
        3. 横向扩展:MySQL集群、负载均衡、读写分离
        4. SQL语句的优化(归根结底是避免全表扫描,对索引进行优化)
     
     
    三、字段设计
        1. 尽量使用整型来表示字符串
           使用关联表的方式来替代enum,字典表
        2. 定长和非定长数据类型的选择
           decimal不会损失精度,存储空间会随数据的增大而增大。double占用固定空间,较大数的存储会损失精度。非定长的还有varchar、text
        3. 尽可能选择小的数据类型和指定短的长度
        4. 尽可能使用not null
          非null字段的处理要比null字段的处理高效些!且不需要判断是否为null。
          null在MySQL中,不好处理,存储需要额外空间,运算也需要特殊的运算符。如select null = null和select null <> null有着同样的结果,只能通过is null和is not null来判断字段是否为null。
          MySQL中每条记录都需要额外的存储空间,表示每个字段是否为null。因此通常使用特殊的数据进行占位,比如int not null default 0、string not null default ''
        5. 字段注释要完整,见名知意
        6. 单表的字段不宜过多(二三十个是极限)
        7. 可以预留字段
     
    四、关联表的设计
        1. 一对多(使用外键)
        2. 多对多(单独新建一张表,将多对多拆分成两个多对一)
        3. 一对一(如商品和商品的明细信息,通常使用相同的主键或者增加一个外键字段)
     
        
    五、存储引擎选择(MyISAM、Innodb)
      差异对比                                        MyISAM                                                                                       Innodb
    文件格式                                  数据和索引是分别存储的,数据.MYD,索引.MYI                 数据和索引是集中存储的,.ibd
    文件能否移动                              能,一张表就对应.frm、MYD、MYI3个文件                      否,因为关联的还有data下的其它文件
    记录存储顺序                              按记录插入顺序保存                                                            按主键大小有序插入
    空间碎片(表文件大小不变)    产生。 定时整理:使用命令optimize table 表名实现           不产生
    事务                                                                       不支持                                                        支持
    外键                                                                    不支持                                                           支持
    锁支持(锁是避免资源争用的一个机制)                      表级锁定                                          行级锁定、表级锁定,锁定力度小并发能力高
     
    锁扩展:
    表级锁(table-level lock):lock tables <table_name1>,<table_name2>... read/write,unlock tables <table_name1>,<table_name2>...。
    其中read是共享锁,一旦锁定任何客户端都不可读;write是独占/写锁,只有加锁的客户端可读可写,其他客户端既不可读也不可写。锁定的是一张表或几张表。
     
    行级锁(row-level lock):锁定的是一行或几行记录。
    共享锁:select * from <table_name> where <条件> LOCK IN SHARE MODE;,对查询的记录增加共享锁;select * from <table_name> where <条件> FOR UPDATE;,对查询的记录增加排他锁。
    这里值得注意的是:innodb的行锁,其实是一个子范围锁,依据条件锁定部分范围,而不是就映射到具体的行上,因此还有一个学名:间隙锁。
    比如select * from stu where id < 20 LOCK IN SHARE MODE会锁定id在20左右以下的范围,你可能无法插入id为18或22的一条新纪录。
     
     
    选择依据:
    如果没有特别的需求,使用默认的Innodb即可。
     
    MyISAM:以读写插入为主的应用程序,比如博客系统、新闻门户网站。
     
    Innodb:更新(删除)操作频率也高,或者要保证数据的完整性;并发量高,支持事务和外键保证数据完整性。比如OA自动化办公系统。
     
    表被锁:SELECT * FROM information_schema.INNODB_TRX 正在执行的事务,kill trx_mysql_thread_id就解除锁定了
     
    六、避免全表扫描要点
        1.查询条件字段不允许进行计算操作
        2.like查询,不能以通配符开头
        3.复合索引只对第一个字段有效
          其原理就是将索引先按照从first_name中提取的关键字排序,如果无法确定先后再按照从last_name提取的关键字排序,也就是说该索引表只是按照记录的first_name字段值有序。
          因此select * from person where first_name = ?是可以利用索引的,而select * from person where last_name = ?无法利用索引。
        4.or,两边条件都有索引可用(一但有一边无索引可用就会导致整个SQL语句的全表扫描)
        5.状态值,不容易使用到索引
    七、如何创建索引
        1.建立基础索引:在where、order by、join字段上建立索引。
        2.优化,组合索引:基于业务逻辑
        如果条件经常性出现在一起,那么可以考虑将多字段索引升级为复合索引
        如果通过增加个别字段的索引,就可以出现索引覆盖,那么可以考虑为该字段建立索引
        查询时,不常用到的索引,应该删除掉
     
    八、水平分割和垂直分割
        水平分割:通过建立结构相同的几张表分别存储数据
        垂直分割:将经常一起使用的字段放在一个单独的表中,分割后的表记录之间是一一对应关系。
     
    九、21个写sql的好习惯
    1. 写完sql后,explain查看执行计划(sql性能优化)
    2. 操作delete或者update时,加上limit 1(sql后悔药)
    3. 设计表的时候,所有表和字段都添加相应的注释(SQL规范优雅)
    4. SQL书写格式,关键字大小保持一致,使用缩进。(SQL规范优雅)
    5. INSERT语句标明对应的字段名称(SQL规范优雅)
    6. 变更SQL操作先在测试环境执行,写明详细的操作步骤以及回滚方案,并在上生产前review。(SQL后悔药)
    7. 设计数据库表的时候,加上三个字段:主键,create_time,update_time。(SQL规范优雅)
    8. 写完SQL语句,检查where,order by,group by后面的列,多表关联的列是否已加索引,优先考虑组合索引。(SQL性能优化)
    9. 修改或删除重要数据前,要先备份,先备份,先备份(SQL后悔药)
    10. where后面的字段,留意其数据类型的隐式转换(SQL性能优化)
    11. 尽量把所有列定义为NOT NULL(SQL规范优雅)
    12. 修改或者删除SQL,先写WHERE查一下,确认后再补充 delete 或 update(SQL后悔药)
    13. 减少不必要的字段返回,如使用select <具体字段> 代替 select * (SQL性能优化)
    14. 所有表必须使用Innodb存储引擎(SQL规范优雅)
    15. 数据库和表的字符集统一使用UTF8(SQL规范优雅)
    16. 尽量使用varchar代替char(SQL优化)
    17. 如果修改字段含义或对字段表示的状态追加时,需要及时更新字段注释。 (SQL规范优雅)
    18. SQL修改数据,养成begin + commit 事务的习惯;(SQL后悔药)
    19. 索引命名要规范,主键索引名为 pk_ 字段名;唯一索引名为 uk _字段名 ; 普通索引名则为 idx _字段名。(SQL规范优雅)
    20. WHERE从句中不对列进行函数转换和表达式计算
    21. 如果修改\更新数据过多,考虑批量进行。
     
     
  • 相关阅读:
    JS 数组总结
    JS 数据类型及其判断
    CSS 优先级
    正则表达式及其使用例子
    常见的图片格式
    React 箭头函数的使用
    手动搭建 react+webpack 开发环境
    JS 函数参数及其传递
    JS 中的 this 指向问题
    JS 中函数的 length 属性
  • 原文地址:https://www.cnblogs.com/nanfengxiangbei/p/14182929.html
Copyright © 2011-2022 走看看