分享

【MySQL进阶学习】优化索引与分区表

 怡红公子0526 2020-04-14

优化索引

MySQL中,有两种方式生成语序结果集,一种是使用file sort(慢查询),一种是按索引顺序扫描(要在经常排序的字段上建立索引)注意:不是索引越多越好!

为索引列选择合适的数据类型

  • 越小的数据类型通常更好:越小的数据类型通常在磁盘、内存和 CPU 缓存中都需要更少的空间,处理起来更快。

  • 简单的数据类型更好:整型数据比起字符,处理开销更小,因为字符串的比较更复杂。IP的存储问题。

  • 主键整型最好。

  • 避免 NULL,含有NULL的列做统计和查询优化很麻烦。

一般原则

  1. 有大量重复值、经常进行范围查询(=、> 、 < 、> =、< =、between、in)和order bygroup by发生的列,可考虑建立聚簇索引。

  2. 经常同时存取多列,且每列都含有重复值可考虑建立组合索引,其前导列一定是使用最频繁的列。

  3. 索引不会包含有 NULL 值的列。只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有 NULL值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为NULL

  4. 尽量使用短索引。对字符串列进行索引,如果可能应该指定一个前缀长度。

  5. 索引列排序。MySQL 查询只使用一个索引,因此如果 where 子句中已经使用了索引的话,那么 order by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序,如果需要最好给这些列创建复合索引。

  6. like 语句操作。一般情况下不鼓励使用 like 操作,如果非使用不可,如何使用也是一个问题。like “%aaa%” 不会使用索引而 like “aaa%”可以使用索引。

  7. 尽量不要在列上进行运算。如,select * from users where YEAR(adddate)<2007,将在每个行上进行运算,这将导致索引失效而进行全表扫描,因此我们可以改成:select * from users where adddate<’2007-01-01′

建立索引,但是不走索引的情况

1.存在null值

select * from 
	表名 
where 
	字段名 is not null;

2.NOT条件
包括:<>、NOT、in、not exists

select * from 
	表名 
where 
	字段名 in (数值1,数值2,,,数值n);

3.LIKE通配符的后匹配

select *from表名where字段名 like '模糊搜索的条件';

4.函数运算

select * from 
	test 
where 
	//比如upper函数
	upper(name)='SUNYANG';

5.数据类型的转换

select * from 
	sunyang 
where 
	id='123';

当查询条件存在隐式转换时,索引会失效。比如在数据库里id存的int类型,但是在查询时,却用了上面的形式,此举例中id是int类型,但是输入了字符类型。

6.复合索引前导列区分不大
参考如下:
MySQL执行计划解读

表分区

概念:表分区就是将一个大表按照mysql提供的几种方式,分成几个小表。
.
日常开发中我们经常会遇到大表的情况,所谓的大表是指存储了百万级乃至千万级条记录的表。这样的表过于庞大,导致数据库在查询和插入的时候耗时太长、性能低下,如果涉及联合查询的情况,性能会更加糟糕。对表进行分区,目的就是减少数据库的负担,提高数据库的效率,通常来讲就是提高表的增删改查效率。
分区是将数据分段划分在多个位置存放,可以是同一块磁盘也可以在不同的机器。分区后,表面上还是一张表,但数据散列到多个位置了。应用程序读写的时候操作的还是大表名字,数据库系统自动去组织分区的数据。

表分区的功能

  • 与单个磁盘或文件系统分区相比,可以存储更多的数据。

  • 很容易就能删除不用或者过时的数据。

  • 一些查询可以得到极大的优化。

  • 涉及到 SUM()/COUNT() 等聚合函数时,可以并行进行。

  • IO 吞吐量更大。

  • 分区允许可以设置为任意大小的规则,跨文件系统分配单个表的多个部分。实际上,表的不同部分在不同的位置被存储为单独的表。

范围分区(Range Partition

通常是使用频率最高的分区,如按月份划分,这样的数据保持均匀性比较好,如果划分的均匀性不是很好,需要考虑其他分区方法。
格式:

CREATE TABLE table_name(....//创建表的格式不变)partition by RANGE(table_column)(PARTITION p0 VALUES LESS THAN (values1),PARTITION p1 VALUES LESS THAN (values2),PARTITION p2 VALUES LESS THAN (values3)...)

实例:可以将一个表通过年份划分成两个分区,2001-2010年、2011-2020。

列表分区(List Partition)

当需要明确控制如何将数据进行分区时,采用这种方式。只能进行单列分区,可以讲数据进行分组,比如按城市分区,几个城市放一起。
格式:

CREATE TABLE table_name(....//创建表不变)partition by LIST(table_column)(PARTITION p0 VALUES IN (0,4,8,12),PARTITION p1 VALUES IN (1,5,9,13), 
	PARTITION p2 VALUES IN (2,6,10,14), 
	PARTITION p3 VALUES IN (3,7,11,15)...)

和范围分区差不多,只不过一个是范围,一个是具体数值。

哈希分区(Hash Partition)

如果数据不是那么容易进行划分,通过这种方式就很灵活了。可以将数据均匀的插入到不同的块,在并发时有利于提高效率,当无法用Range分区时,就可以用Hash分区。
格式:

CREATE TABLE table_name(....//创建表不变)
 PARTITION BY HASH(table_column) 
 PARTITIONS nums;

和上述两种分表的格式不是太相同,只需要设置nums为分区个数就行了,是一个整数值。

复合分区

未过多讲述,如想了解,请移步–>全面总结Oracle中的分区表

参考笔记来自老师授课的教案:番茄发烧了

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多