MySQL索引优化

不使用索引的情况

  1. 如果 mysql 估计使用索引比全表扫描更慢,则不使用索引。
    例如:如果 key_part 1 均匀分布在 1 和 100 之间,下列查询中使用索引就不是很好:
1
SELECT * FROM table_name where key_part1 > 1 and key_part1 < 90;
  1. 如果使用 heap 表并且 where 条件中不用=索引列,其他 > 、 < 、 >= 、 <= 均不使 用索引(MyISAM 和 innodb 表使用索引);

  2. 使用 or 分割的条件,如果 or 前的条件中的列有索引,后面的列中没有索引,那么涉及到的索引都不会使用。

  3. 如果创建复合索引,如果条件中使用的列不是索引列的第一部分;(不是前缀索引)

  4. 如果 like 是以%开始;

  5. 对 where 后边条件为字符串的一定要加引号,字符串如果为数字 mysql 会自动转 为字符串,但是不使用索引。

查看索引使用情况

如果索引正在工作, Handler_read_key 的值将很高,这个值代表了一个行被索引值读的次数,很低的值表明增加索引得到的性能改善不高,因为索引并不经常使 用。

Handler_read_rnd_next 的值高则意味着查询运行低效,并且应该建立索引补救。这个值的含义是在数据文件中读下一行的请求数。如果你正进行大量的表扫描,

该值较高。通常说明表索引不正确或写入的查询没有利用索引。

语法:

1
show status like 'Handler_read%';
阅读更多

MySQL索引小结

索引的作用

索引的出现其实就是为了提高数据查询的效率,用于快速找出在某个列中有一特定值的行。

阅读更多

MySQL临时表

MySQL 临时表分为“内存临时表”和“磁盘临时表”,其中内存临时表使用 MySQL 的 MEMORY 存储引擎,磁盘临时表使用 MySQL 的 MyISAM 存储引擎;一般情况下,MySQL 会先创建内存临时表,但内存临时表超过配置指定的值后,MySQL 会将内存临时表导出到磁盘临时表。
MySQL 临时表在我们需要保存一些临时数据时是非常有用的。临时表只在当前连接可见,当关闭连接时,Mysql 会自动删除表并释放所有空间。

阅读更多

记一次MySQL大表空间收缩

最近收到 MySQL 数据库磁盘空间使用率过高的报警,发现其中的一个表空间占用竟然高达三百多 G。删除了一半多的数据后,可是表文件大小还是没变,当时就懵了。
请教 DBA 才知道删除大量数据后存在数据空洞,MySQL 不会自动收缩表空间,需要手工操作。

产生原因

  1. InnoDB 里的数据都是用 B+树的结构组织的,每当删除了一条记录后,InnoDB 引擎只会把这个记录标记为删除,而在一段时间内的大量删除操作,会使这种留空的空间变得比存储列表内容所使用的空间更大。

  2. 记录的复用只限定符合范围条件的数据。比如说删除一条 ID 为 400 的数据,当执行插入操作 ID 为 400 前后的数据时,MySQL 可能会复用这个位置。但如果某个空白空间一直没有被大小合适的数据占用,仍然无法将其彻底占用,就形成了碎片。

  3. 如果是随机插入数据也会造成数据空洞。

解决方案

  1. 对数据导出后进行收缩,然后导入数据。
  2. 重建表

目前没有导出数据的条件,采用重建表的方法,可以采用alter table A engine=InnoDB 命令。
MySQL 5.6 版本开始引入了 Online DDL,允许在表上执行 DDL 的操作(比如创建索引)的同时不阻塞并发的 DML 操作 和 查询(select)操作。

  • Algorithm=Inplace :为了避免表拷贝导致的实例性能问题(空间、I/O 问题),建议在 DDL 中包含该选项。如果 DDL 操作不支持 Algorithm=Inplace 方式,DDL 操作会立刻返回错误。

  • Lock=None :为了在 DDL 操作过程中不影响业务的 DML 操作,建议在 DDL 中包含该选项。如果 DDL 操作不支持 Lock=None (允许并行 DML 操作)选项,DDL 操作会立刻返回错误。

所有的 DDL 操作均建议在业务低峰期进行,避免对业务产生影响。经过测试,删除表的数据后,对应的磁盘空间也正常释放了。

数据库设计-约束

数据库约束是为了保证数据的完整性(正确性)而实现的一套机制。主要分为五大约束:

  1. 主键约束(Primay Key Coustraint): 唯一性,非空性
1
2
3
# 添加主键约束(将UserId作为主键)
alter table UserId
   add constraint PK_UserId primary key (UserId);
  1. 唯一约束 (Unique Counstraint):唯一性,可以空,但只能有一个
1
2
3
# 添加唯一约束(身份证号唯一,因为每个人的都不一样)
alter table UserInfo
   add constraint UQ_IDNumber unique(IdentityCardNumber);
  1. 检查约束 (Check Counstraint):对该列数据的范格式的限制(如:年性别等)
1
2
3
4
5
# 添加检查约束 (对年龄加以限定 20-40 岁之间)
alter table UserInfo
   add constraint CK_UserAge check (UserAge between 20 and 40);
alter table UserInfo
   add constraint CK_UserSex check (UserSex=’男’ or UserSex=’女′);
  1. 默认约束 (Default Counstraint):该数据的默认值
1
2
3
# 添加默认约束(如果地址不填 默认为“地址不详”)
alter table UserInfo
   add constraint DF_UserAddress default (‘地址不详’) for UserAddress;
  1. 外键约束 (Foreign Key Counstraint):需要建立两表间的关系并引用主表的列
1
2
3
# 添加外键约束 (主表 UserInfo 和从表 UserOrder 建立关系,关联字段 UserId)
alter table UserOrder
   add constraint FK_UserId_UserId foreign key(UserId)references UserInfo(UserId);
阅读更多

数据库设计-范式

范式是符合某一种级别的关系模式的集合。关系型数据库中的关系必须满足一定的要求,满足不同程度要求的为不同范式。
目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、Boyce-Codd 范式(BCNF)、第四范式(4NF)和第五范式(5NF)。
范式越高,冗余最低,一般到三范式即可,再往上,表越多,可能导致查询效率下降。所以有时为了提高运行效率,可以让数据冗余

阅读更多

MySQL批量删除大量数据

公司线上的 MySQL 数据库每半年都需要删除大量的无效数据,只保留部分数据,因为历史遗留问题有几个表需要清理二三亿条数据,少的也有几千万,任务非常艰巨。

阅读更多