MySQL数据库优化

说到数据库的优化,我在MySQL数据库引擎这篇文章当中对使用MyIsam存储引擎的表和使用InnoDB存储引擎的表之间对比的过程中发现,InnoDB存储引擎的表插入速度十分的慢,我创建了一个存储过程直接往数据库中插入一千万条数据的时候,等了大约一二十分钟的样子,才插入了一百万数据,但是MyIsam存储引擎的表只用了五分钟的时间,一直拖到晚上十一点多,还是没有完成,无奈我只能改为插入一百万的数据作为测试。后来一想到,我的InnoDB存储引擎的表在插入的时候可能默认的是自动提交,这样的话每一次插入都要打开连接一次,十分耗时,解决方案是批处理,开始的时候把自动提交关闭,然后存储过程执行结束的时候开启自动提交即可。从这里可以看出优化是多么的重要。



批处理优化


正如上面所说的那样,批量的插入数据和一次次的插入数据效率是有很大的差距的。比如说:

create table testOptimize( id int unsigned primary key auto_increment, name varchar(20) );
创建这样的一个表,默认了存储引擎是InnoDB,因为InnoDB是支持事务的。

mysql> create procedure insertOptimize()
    -> begin
    -> set @i = 1;
    -> while @i <= 1000
    -> do 
    -> insert into testOptimize(name) values(concat("wy", @i));
    -> set @i = @i + 1;
    -> end while;
    -> end//
Query OK, 0 rows affected (0.38 sec)

mysql> call insertOptimize//
Query OK, 0 rows affected (7.39 sec)

mysql> \d ;
mysql> set autocommit = 0;
Query OK, 0 rows affected (0.15 sec)

mysql> call insertOptimize;
Query OK, 0 rows affected (0.65 sec)

mysql> set autocommit = 1;
Query OK, 0 rows affected (0.14 sec)

上面是一段存储过程:插入一千条数据的时间的对比,从这里面可以直接看出,差距还是比较大的,默认的情况下自动提交,这时候的执行时间是7.39秒,而将自动提交关闭,最后开启自动提交的方式,执行时间为1s以内,这样的差距对于大批量的数据插入差距更是十分明显的。


批量插入的另一种方式:


insert into testOptimize(name) values("wy1"),("wy2"),("wy3");

打开一次连接插入多次数据。


存储过程在上面的例子中已经用到了,这里不再举例子了。



触发器


创建一个触发器,在插入testOptimize表的同时,要往testOptimize2表中插入数据。

CREATE trigger testTriger before insert on testOptimize for each row
begin
insert into testOptimize2(id, name) values(new.id, new.name);
end

这里直接调用上一步中的存储过程即可。



索引优化


数据库优化中最常见的也是最重要的手段之一,通过索引通常可以帮助用户解决大多数的SQL性能问题。

MySQL数据库引擎这篇文章中已经介绍了MyIsam存储引擎的主要特性,这里再简要说明一下,表的数据和索引分开来存储,各自是独立的文件,innoDB是存放在一个文件当中。

MySQL不支持函数索引,但是可以对列的某一部分进行索引,可以只取出四个字符进行索引。这个特性可以缩小索引文件的大小,可以根据这个特性去设计采用谁去生成索引。



存在索引且会用到索引


1. 查看SQL语句影响的行数

对于创建了索引的列:

mysql> desc select * from testOptimize where id = 1\G;
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: testOptimize
         type: const
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: const
         rows: 1
        Extra: 
1 row in set (0.00 sec)
对于没有进行索引的列:

mysql> desc select * from testOptimize where name = "wy1"\G;
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: testOptimize
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 3242
        Extra: Using where
1 row in set (0.00 sec)

我们会看到中间的rows信息的差别:上面创建了索引的列的查询行数为1,而下面的没有创建索引的列的查询行数为3242,应该说,如果数据量比较大的时候,明显是查询的行数越少效率会越高。


对下面这句没有索引的进行优化,也就是说对他创建索引,当然索引在使用时注意,不要随便建索引,因为索引会占据很大的空间存储。一般的是对于效率很低的查询语句中没有用到索引的列进行创建索引以提升速度。

mysql> alter table testOptimize add index testOptimize(name);



2. like的查询


后面如果是常量且只有%不在第一个字符的时候,索引才可能用得上的。

比如(这里name已经创建了索引):

desc select * from testOptimize where name like "wy1%"\G;
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: testOptimize
         type: range
possible_keys: testOptimize
          key: testOptimize
      key_len: 23
          ref: NULL
         rows: 337
        Extra: Using where; Using index
1 row in set (0.22 sec)

那么将%放在第一位的话:

mysql> desc select * from testOptimize where name like "%wy1"\G;
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: testOptimize
         type: index
possible_keys: NULL
          key: testOptimize
      key_len: 23
          ref: NULL
         rows: 3242
        Extra: Using where; Using index
1 row in set (0.25 sec)



3. 如果某一列有索引,使用column_name is null 可能会使用索引。

这里的影响行数是1,而不是全部的数据。

mysql> desc select * from testOptimize where name is null\G;
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: testOptimize
         type: ref
possible_keys: testOptimize
          key: testOptimize
      key_len: 23
          ref: const
         rows: 1
        Extra: Using where; Using index
1 row in set (0.40 sec)



存在索引但不使用的情况


1. 如果MySQL估计使用索引比全表扫描的更慢的话,不使用索引。

2. 用or连接的条件如果or前面的条件中的列有索引,后面的没有索引,那么涉及到索引不会被用到。

<strong><span style="font-size:18px;">mysql> alter table testOptimize drop index testOptimize;
Query OK, 0 rows affected (0.16 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc select * from testOptimize where name = "wy1" or id = 111\G;
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: testOptimize
         type: ALL
possible_keys: PRIMARY
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 3242
        Extra: Using where
1 row in set (0.00 sec)</span></strong>

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目录 1. DB2 1.1. 创建一个返回结果集的存储过程\自定义函数 12 1.2. DB2 高级应用 14 1.3. 删除表数据时候出现日志已满的解决方法 24 1.4. DB2快照函数全解析 25 1.5. DB2中的22个命令小技巧 26 1.6. DB2实现类型ORACLE的一些功能 29 1.7. 字符数据类型转换的时候需要注意的问题(原) 30 1.8. 本地谓词的使用注意(原) 31 1.9. windows/Linux或Unix下查看DB2端口号 31 1.10. 尽量让fetch first n row only或者分页的时候结合optimize for n rows使用(原) 32 1.11. 格式化字符串(原) 33 1.12. 10大DB2优化技巧 33 1.13. 使用DB2的整数转换浮点小数时注意(原) 41 1.14. 使用递归制造测试数据(原) 42 1.15. 尽量使用自定义函数来代替存储过程 42 1.16. VALUES(…) 与 VALUES …的区别(原) 44 1.17. DB2的表锁和行锁 45 1.18. 修改表结构后不允许对表进行任何操作(原) 57 1.19. 解决暂挂表(原) 58 1.20. DB2LOOK语法及使用 58 导出表结构的表结构脚本 59 1.21. DB2的函数大全 64 1.22. DB2数据库为单个会话锁定技巧 64 1.23. EXISTS和COUNT(*)的使用(原) 68 1.24. 如果表比较大,进行COUNT的时候,可选择COUNT_BIG(*) 69 1.25. 序列(SEQUENCE) (原) 69 1.26. 数据的导入和导出 69 1 加载数据: 69 2 卸载数据: 70 3 在Load过程中使用的Exception 表有何作用,该如何创建?(原) 70 4如何导出(EXPORT),导入(LOAD)包含由公式生成字段的表 70 5 LOAD命令和自生成列值 72 6 用load命令和identityoverride参数向有identity列的表中装载数据后的注意事项 74 1.27. 利用快照函数查询数据库服务器本地以及远程的连接数 74 1.28. 查看SQL的执行计划 74 1.29. 如何查看数据库ABC的配置文件的内容? 75 1.30. 查看是哪张表挂起(原) 75 1.31. 导出(导入)数据库的所有表数据(db2move) 75 1.32. 备份数据库,恢复数据库 75 1.33. 建立数据库、缓冲池、表空间、表案例 77 1.34. 建立别名 78 1.35. 建立视图 78 1.36. 建立唯一性索引 78 1.37. 查看表的索引 79 1.38. 查看表 79 1.39. 建立触发器 79 1.40. 查看存储过程 79 1.41. view application 79 1.42. kill application 79 1.43. lock table(x) 79 1.44. lock table(s) 80 1.45. 列出所有的系统表 80 1.46. 列出系统数据库目录 80 1.47. 显示当前活动数据库 80 1.48. 查看命令选项 80 1.49. 表空间 80 1.50. 表空间容器 80 1.51. 如何知道SEQUENCE的状况 81 1.52. 如何知道SCHEMA的状况 81 1.53. 如何知道INDEX的状况 81 1.54. 查看装载数据库的instance 81 1.55. 创建数据库的instance 81 1.56. 创建数据库的catalog 81 1.57. 如何在命令行下执行DB2脚本(script) 82 1.58. 怎么样获取表结构以及索引的信息 82 1.59. 如果怀疑应用程序有死锁现象,如何确认是否死锁,并判断是哪些程序引起的死锁? 84 1.60. 数据库创建以后相关的目录和文件都有哪一些? 85 1.61. 自增列(IDENTITY) 86 1.62. 修改表结构的注意事项(原) 86 1.63. 可使用VALUES 来代替多个[not] in的条件语句 87 1.64. 计算数据库缓冲池的命中率公式 87 1.65. 查看表空间状态 88 1.66. UPDATE的N种用法 88 Examples 88 1.67. 查看表状态的快照命令 90 1.68. RUNSTATS的使用案例 91 1.69. Bufferpool设置过大导致数据库无法启动的解决方案 98 1.70. 查看DB2是否存在僵尸进程 98 1.71. 监控执行成本最高的SQL语句 99 1.72. 监控运行最长的SQL语句 99 1.73. 给表增加generated al

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值