稀疏索引只为某些搜索码值建立索引记录;在搜索时,找到其最大的搜索码值小于或等于所查找记录的搜索码值的索引项,然后从该记录开始向后顺序查询直到找到为止
叶子节点存储的是主键和索引列
InnoDB 主键走聚集索引,其他走稀疏索引
MyISAM 全是走稀疏索引
联合索引最左匹配原则
索引只能用于查找key是否存在(相等),遇到范围查询(>、<、between、like左匹配)等就不能进一步匹配了,后面的条件退化为线性查找
例如创建 union index (a , b ,c) 查(a,b)走索引,查(a,c)走不了索引
大表优化
查询限定数据范围
比如:我们当用户在查询订单历史的时候,我们可以控制在一个月的范围内
读写分离
主库负责写,从库负责读
垂直拆分
概述
简单来说垂直拆分是指数据表列的拆分,把一张列比较多的表拆分为多张表
优点
可以使得列数据变小,在查询时减少读取的Block数,减少I/O次数。此外,垂直分区可以简化表的结构,易于维护
缺点
主键会出现冗余,需要管理冗余列,并会引起Join操作,可以通过在应用层进行Join来解决。此外,垂直分区会让事务变得更加复杂
水平拆分
概述
保持数据表结构不变,通过某种策略存储数据分片。这样每一片数据分散到不同的表或者库中,达到了分布式的目的。 水平拆分可以支撑非常大的数据量,水平拆分最好分库
优点
支持非常大的数据量存储,应用端改造也少
缺点
拆分会带来逻辑、部署、运维的各种复杂度大大提高,所以实际中使用逻辑上的分片方案来代替
实际中使用的方案
客户端代理: 分片逻辑在应用端,封装在jar包中,通过修改或者封装JDBC层来实现。 当当网的 Sharding-JDBC 、阿里的TDDL是两种比较常用的实现
中间件代理: 在应用和数据中间加了一个代理层。分片逻辑统一维护在中间件服务中。 我们现在谈的 Mycat 、360的Atlas、网易的DDB等等都是这种架构的实现
高性能实践的一些规范命令规范
所有数据库对象名称必须使用小写字母并用下划线分割
所有数据库对象名称禁止使用 MySQL 保留关键字(如果表名中包含关键字查询时,需要将其用单引号括起来)
数据库对象的命名要能做到见名识意,并且最后不要超过 32 个字符
临时库表必须以 tmp_为前缀并以日期为后缀,备份表必须以 bak_为前缀并以日期 (时间戳) 为后缀
所有存储相同数据的列名和列类型必须一致(一般作为关联列,如果查询时关联列类型不一致会自动进行数据类型隐式转换,会造成列上的索引失效,导致查询效率降低)
设计规范
所有表必须使用 Innodb 存储引擎
数据库和表的字符集统一使用 UTF8
所有表和字段都需要添加注释
尽量控制单表数据量的大小,建议控制在 500 万以内
谨慎使用 MySQL 分区表
尽量做到冷热数据分离,减小表的宽度
禁止在表中建立预留字段
禁止在数据库中存储图片,文件等大的二进制数据
优先选择符合存储需要的最小的数据类型
避免使用 TEXT,BLOB 数据类型,最常见的 TEXT 类型可以存储 64k 的数据
避免使用 ENUM 类型
尽可能把所有列定义为 NOT NULL
使用 TIMESTAMP(4 个字节) 或 DATETIME 类型 (8 个字节) 存储时间
同财务相关的金额类数据必须使用 decimal 类型
索引规范
限制每张表上的索引数量,建议单张表索引不超过 5 个
禁止给表中的每一列都建立单独的索引
每个 Innodb 表必须有个主键
常见索引列建议
出现在 SELECT、UPDATE、DELETE 语句的 WHERE 从句中的列
包含在 ORDER BY、GROUP BY、DISTINCT 中的字段
并不要将符合 1 和 2 中的字段的列都建立一个索引, 通常将 1、2 中的字段建立联合索引效果更好
多表 join 的关联列
选择索引列的顺序
区分度最高的放在联合索引的最左侧(区分度=列中不同值的数量/列的总行数)
尽量把字段长度小的列放在联合索引的最左侧(因为字段长度越小,一页能存储的数据量越大,IO 性能也就越好)
使用最频繁的列放到联合索引的左侧(这样可以比较少的建立一些索引)
避免建立冗余索引和重复索引
尽量避免使用外键约束
SQL语句规范
禁止使用 SELECT * 必须使用 SELECT 查询
禁止使用不含字段列表的 INSERT 语句
避免使用子查询,可以把子查询优化为 join 操作
避免使用 JOIN 关联太多的表
对应同一列进行 or 判断时,使用 in 代替 or
禁止使用 order by rand() 进行随机排序
WHERE 从句中禁止对列进行函数转换和计算
在明显不会有重复值时使用 UNION ALL 而不是 UNION
拆分复杂的大 SQL 为多个小 SQL
对于连续数值,使用BETWEEN不用IN:SELECT id FROM t WHERE num BETWEEN 1 AND 5
尽量避免在 WHERE 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描
常用命令