zoukankan      html  css  js  c++  java
  • 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等环境软件安装
  • 相关阅读:
    (二分查找 拓展) leetcode 69. Sqrt(x)
    (二分查找 拓展) leetcode 162. Find Peak Element && lintcode 75. Find Peak Element
    (链表) lintcode 219. Insert Node in Sorted Linked List
    (二分查找 拓展) leetcode 34. Find First and Last Position of Element in Sorted Array && lintcode 61. Search for a Range
    (最短路 Floyd) P2910 [USACO08OPEN]寻宝之路Clear And Present Danger 洛谷
    (字符串 数组 递归 双指针) leetcode 344. Reverse String
    (二叉树 DFS 递归) leetcode 112. Path Sum
    (二叉树 DFS 递归) leetcode 101. Symmetric Tree
    (二叉树 递归) leetcode 144. Binary Tree Preorder Traversal
    (二叉树 递归 DFS) leetcode 100. Same Tree
  • 原文地址:https://www.cnblogs.com/Adam-Ye/p/14850912.html
Copyright © 2011-2022 走看看