①插入多条数据时,使用批量插入,而非多次单条插入;②建议使用手动事务提交,减少频繁开启关闭事务;③使用主键顺序插入,顺序插入性能要高于乱序插入
1.1、大批量插入数据
如果一次性插入大批量数据,使用insert语句插入性能较低,此时可以使用MySQL数据库提供的load指令进行插入。使用load指令需要执行以下三个步骤:
①客户端连接时,加上参数 --local -infile
mysql --local -infile -u root -p
②设置全局参数local_infile为1,开启从本地加载文件导入数据的开关
set global local_infile=1;
③执行load指令,将准备好的数据加载到表结构中
load data local infile '/root/sql.log' into table 'user' fields terminated by ',' lines terminated by '\n';
--'/root/sql.log' 指文件存放路径
--'user' 文件数据存放的表
--fields terminated by ',' 字段间的分隔符是','
--lines terminated by '\n' 每行数据间的分隔符是换行
数据组织方式:在InnoDB存储引擎中,表数据都是根据主键顺序组织存放的,这种存储方式的表称为索引组织表。
页分裂:页可以为空,也可以填充一半,也可以填充100%。每个页包含2-N行数据(如果一行数据够大,会行溢出),根据主键排列。
页合并:当删除一行数据时,实际上记录并没有被物理删除,只是记录被标记(flaged)为删除并且它的空间允许提起记录声明使用。当页中删除的记录达到MERGE_THRESHOLD(默认为页的50%),InnoDB会开始寻找最近的页,看看是否可以将两个页合并,优化空间使用。
主键乱序插入时,可能产生页分裂现象,需要重新维护链表指针。
主键设计原则:
①满足业务需求的情况下,尽量降低主键的长度;②插入数据时,尽量选择顺序插入,选择使用AUTO_INCREMENT自增主键;③尽量不要使用UUID做主键或者其他自然主键,如身份证号;④业务操作时,避免对主键进行修改
①using filesort:通过表的索引或全部扫描,读取满足条件的数据,然后在排列缓冲区sort_buffer中完成排序;所有不是通过索引直接返回排序结果的排序都叫filesort排序。
②using index:通过有序索引顺序扫描直接返回有序数据,这种情况即using index,不需要额外排序,操作效率高。
③backward index scan:反向扫描索引。
优化原则:
①根据排序字段建立合适的索引,多字段排序时,也遵循最左前缀法则;
②尽量使用覆盖索引;
③多字段排序,一个升序一个降序,此时需要注意联合索引在创建时的规则(asc/desc);
create index index_name on table_name(col1 asc,col2 desc);
--命名规范:index_name通常命名为index_xxx_ad,a即asc,d即desc
--按col1升序,按col2降序
④如果不可避免的出现filesort,大数据量排序的时,可以适当增大排序缓冲区(sort_buffer_size,默认256K)的大小。
①在分组操作时,可以通过建立索引来提高效率;
②分组操作时,索引的使用也满足最左前缀法则;
limit一个常见的问题是limit 10000000,10(10000000只是一个例子),此时MySQL先将前10000010记录排序,然后返回10000000-10000010的记录,其他记录丢弃,查询排序的代价非常大。
优化方案:覆盖索引+子查询优化;
select * from tb1,(select id from tb1 order by id limit 10000000,10) a where tb1.id=a.id;
MYISAM存储引擎把一个表的总行数存储在磁盘上,执行count(*)会直接返回这个数,效率很高;
InnoDB在执行count(*)时,需要把数据全读出来再累计计数。
优化方案:自己计数
count的几种用法:
count(主键):遍历整张表,把每一行的id取出,返回给服务层,服务层直接进行累加。
count(字段):没有not null约束,遍历整张表,取出改字段返回给服务层,服务层判断是否为null,不为null则直接累加;有not null约束,服务层直接累加;
count(1):遍历整张表但不取值,服务层对返回的每一个放一个‘1’进去,直接累加;
count(*):InnoDB并不会把所有字段取出,而是专门做了优化,不取值,服务层直接进行累加。
在MySQL中,count(*)的效率是最高的;count(*)≈count(1)>count(主键)>count(字段)
InnoDB的行锁是针对索引加的锁,不是针对记录加的锁,并且该索引不能失效,否则会从行锁升级为表锁,并发性能大大降低。