• 1、schema和数据类型优化


    1、Schema优化

    Schema的设计非常重要,良好的Schema设计能够提高mysql的性能

    1.1.一些错误的Schema设计:

    太多的列

    MySQL的存储引擎API工作时需要在服务器层和存储引擎层之间通过行缓冲格式拷贝数据,然后在服务器层将缓冲内容解码成各个列。从行缓冲中将编码过的列转换成行数据结构的操作代价是非常高的。MyISAM的定长行结构实际上与服务器层的行结构正好匹配,所以不需要转换。然而,MyISAM的变长行结构和InnoDB的行结构则总是需要转换。转换的代价依赖于列的数量。如果计划使用数千个字段,必须意识到服务器的性能运行特征会有一些不同。 

    太多的关联

    所谓的“实体-属性-值”(EAV)设计模式是一个常见的糟糕设计模式,尤其是在MySQL下不能靠谱地工作。MySQL限制了每个关联操作最多只能有61张表,但是EAV数据库需要许多自关联。我们见过不少EAV数据库最后超过了这个限制。事实上在许多关联少于61张表的情况下,解析和优化查询的代价也会成为MySQL的问题。一个粗略的经验法则,如果希望查询执行得快速且并发性好,单个查询最好在5个表以内做关联。 

    1.2.小结

    1、 尽量避免过度设计,例如会导致及其复杂查询的schema设计,或者有很多列的表的设计

    2、 使用小而简单的合适数据类型,除非真实数据模型中有确切的需要,否则应该尽可能地避免使用null值

    • 如果查询中包含可为NULL的列,对Mysql来说更难优化,因为可为NULL的列使得索引,索引统计和值比较都更复杂。
    • 含NULL复合索引无效.
    • 可为NULL的列会使用更多的存储空间,在Mysql中也需要特殊处理。
    • 当可为NULL的列被索引时,每个索引记录需要一个额外的字节,在MyISAM里甚至还可能导致固定大小的索引(例如只有一个整数列的索引)变成可变大小的索引。

     

    2、数据类型优化

    mysql支持很多数据类型,在项目开发时,如何根据业务选择正确的数据类型非常重要

    2.1.原则

    • 更小的通常更好
      • 一般情况下,应该尽量使用可以正常存储数据的最小数据类型。更小的数据类型通常更快,因为它们占用更少的磁盘、内存和CPU缓存,并且处理时需要的CPU周期也更少
    • 简单就好
      • 简单数据类型需要更少的CPU周期,整型比字符串操作代价更低,比如应该用整型存储ip地址,使用mysql内建的date,time,datetime而不是字符串储存时间
    • 尽量避免null
      • 通常情况下最好制定列为not null,因为可为null的列使得索引、索引统计和值比较都更复杂。可为null的列占据更多的存储空间,被索引时也需要一个额外的字节
    • 选择数据类型时首先确定合适的大类型,比如数字、字符串、时间,然后选择具体类型

    2.2.整数类型

    数字有两个类型:整数和实数,如果存整数可以选择

    TINYINT , SMALLINT , MEDIUMINT , INT , BIGINT 分别使用 8 16 24 32 64位存储空间,存储的值范围从 -2的(N-1)次方到2的(N-1)次方-1,N是存储空间位数

    整数类型有可选的UNSIGNED属性,表示不允许负值,可以使正数的上限提高一倍

    mysql可以为整数类型指定宽度,比如INT(11),但是没有什么太大意义,INT(1)和INT(20)是相同的

    2.3.实数类型

    实数就是带小数部分的数字。然而,它们不只是为了存储小数部分,也可以使用DECIMAL存储比BIGINT还大的整数

    CPU不支持对DECIMAL的直接计算,在MySQL5.0以及更高版本中,MySQL服务器自身实现了对DECIMAL的高精度计算,相对而言,CPU直接支持原生浮点计算,所以浮点运算明显更快

    浮点类型在存储同样范围的值时,通常比DECIMAL使用更少的控件,FLOAT使用4个字节,DOUBLE占用8个字节,DOUBLE相比FLOAT有更高的精度和更大的范围,Mysql使用DOUBLE作为内部浮点计算的类型,在数据量较大时采用BIGINT

    2.4.字符串类型

    VARCHAR和CHAR类型是最主要的字符串类型

    VARCHAR

    VARCHAR类型用于存储可变长字符串,是最常见的字符串数据类型,他比定长类型更省空间,因为它仅仅使用必要的空间

    VARCHAR需要使用1或者2个额外字节记录字符串的长度,如果列的最大长度小于等于255字节,则只使用一个字节表示,否则使用2个字节,MySQL 5.0以上的VARCHAR在存储和检索时会保留末尾空格,过长的VARCHAR存储为BLOB

    在以下场景使用VARCHAR:

    • 字符串列的最大长度比平均长度大很多
    • 列的更新很少

    注:VARCHAR虽然是可变长字符串,但是还是要根据业务需要设置长度,因为变长是需要消耗性能的,如果差距较大意味着CPU消耗大

    使用VARCHAR(5)和VARCHAR(200)存储‘hello’的空间开销是一样的,但是更长的列会消耗更多的了内存,因为mysql通常会分配固定大小的内存来保存内部值。最好的策略是只分配真正需要的空间

    CHAR

    CHAR是定长的,当存储CHAR时会删除所有的末尾空格,CHAR适合存储很短的字符串,或者所有值都接近同一个长度,对于经常变动的值CHAR的表现也比VARCHAR要好很多

    2.5.日期和时间类型

    mysql有很多类型保存日期和时间值,比如YEAR和DATE,mysql能存储的最小时间粒度为秒,mysql提供两种近似的日期类型,DATETIME和TIMESTAMP,在很多场景他们是类似的,但是也有区别

    DATETIME

    这个类型能保存大范围的值,从1001年到9999年,精度为秒,使用8个字节空间

    TIMESTAMP

    TIMESTAMP类型保存了从1970年1月1日午夜以来的秒数,只使用4个字节的存储空间,范围要比DATETIME小很多,只能表示1970年到2038年

    TIMESTAMP 的特殊属性: 

    在插入数据时如果没有指定值,会自动填充为当前时间。 

    TIMESTAMP 默认为 NOT NULL。 

    通常应该尽量使用 TIMESTAMP,因为它比 DATETIME 空间效率更高。 

    如果需要存储比秒更小粒度的日期和时间值,可以使用BIGINT类型存储微秒级别的时间截,或者使用DOUBLE存储秒之后的小数部分。 

    Linux等环境软件安装
  • 相关阅读:
    《信号检测与估计》课程学习大纲
    测试的具体工作有哪些?
    GIT 身份验证失败问题fatal: Authentication failed for 'http:xxxxxxxxxx.git/'
    编译器的符号表管理
    node.js请求css、js静态资源页面不生效
    CF1626A Equidistant Letters 题解
    Vue父组件调用子组件事件的两种方法
    Vue子组件调用父组件事件的三种方法
    Vue高阶用法:provide / inject
    逃逸分析
  • 原文地址:https://www.cnblogs.com/Adam-Ye/p/14850912.html
Copyright © 2020-2023  润新知