索引对查询有着重要的作用,对索引的认识是进行数据库性能提升的起点,数据库的优化一般是从两个方面,第一个是对SQL语句进行优化,第二是优化数据库表的设计包括索引的建立,这里主要记录第二种的相关学习,当数据库数据量很大的时候,索引能够极大的提高查询速度,本人现在面临的是千万条数据的数据表,遍历所有数据需要花上几分钟的时间,一般的查询都需要几十秒,这个肯定是不能接受的,建立索引后的查询速度为一秒左右,极大的提高了性能。
建表原则
表设计:3NF
字段:
- 越小的数据类型通常更好:越小的数据类型通常在磁盘、内存和CPU缓存中都需要更少的空间,处理起来更快。
- 简单的数据类型更好:整型数据比起字符,处理开销更小,因为字符串的比较更复杂。在MySQL中,应该用内置的日期和时间数据类型,而不是用字符串来存储时间;以及用整型数据类型存储IP地址。
- 尽量避免NULL:应该指定列为NOT NULL,除非你想存储NULL。在MySQL中,含有空值的列很难进行查询优化,因为它们使得索引、索引的统计信息以及比较运算更加复杂。你应该用0、一个特殊的值或者一个空串代替空值。
- 单表字段不宜过多:通常是二三十个
存储引擎:InnoDB(高并发写)与MyIsam的选择:事务、行锁、外键、索引
索引建立
- 类型:普通、唯一、主键、全文
- 位置:
- where
- join on
- order by
- 原则:
- 对读多写少的场景建立索引(索引可以提高读性能,但是会降低写性能),如果不常用到,则应该删除
- 不对重复值多的字段建立索引
- 如果条件经常出现在一起,则考虑将多个字段建立复合索引。复合索引只对第一个字段有效,将频率高的字段放前面(复合索引只查一次索引表)
- 如果添加个别字段的索引,就可以应用到覆盖索引,则考虑为该字段建立索引。
- 语句优化(避免索引失效):查询所有年龄>18的曾姓人名
- 字段要独立出现(id + 1 = xxx则不走索引)
- like查询不以%开头(这种一般采用第三方的全文索引支持)
- or,两边条件都要有索引可用(否则会全表扫描)
- 尽量走覆盖索引
集群
- 分表:横向切割、垂直切割
- 分库:业务表切割
- 读写分离:SpringAOP动态数据源切换
服务器参数配置
show variables like 'max_connections';
max_connections
,最大客户端连接数table_open_cache
,表文件句柄缓存(表数据是存储在磁盘上的,缓存磁盘文件的句柄方便打开文件读取数据)key_buffer_size
,索引缓存大小(将从磁盘上读取的索引缓存到内存,可以设置大一些,有利于快速检索)innodb_buffer_pool_size
,Innodb
存储引擎缓存池大小(对于Innodb
来说最重要的一个配置,如果所有的表用的都是Innodb
,那么甚至建议将该值设置到物理内存的80%,Innodb
的很多性能提升如索引都是依靠这个)innodb_file_per_table
(innodb
中,表数据存放在.ibd
文件中,如果将该配置项设置为ON
,那么一个表对应一个ibd
文件,否则所有innodb
共享表空间)
标识符选择
-
选择合适的标识符是非常重要的。选择时不仅应该考虑存储类型,而且应该考虑MySQL是怎样进行运算和比较的。一旦选定数据类型,应该保证所有相关的表都使用相同的数据类型。
-
整型:通常是作为标识符的最好选择,因为可以更快的处理,而且可以设置为AUTO_INCREMENT。
-
字符串:尽量避免使用字符串作为标识符,它们消耗更好的空间,处理起来也较慢。而且,通常来说,字符串都是随机的,所以它们在索引中的位置也是随机的,这会导致页面分裂、随机访问磁盘,聚簇索引分裂(对于使用聚簇索引的存储引擎)。