|搞懂这些SQL优化技巧,面试横着走( 四 )


①大批量插入数据
如果同时执行大量的插入 , 建议使用多个值的 INSERT 语句(方法二) 。 这比使用分开 INSERT 语句快(方法一) , 一般情况下批量插入效率有几倍的差别 。
方法一:
insert into T values(1,2); insert into T values(1,3); insert into T values(1,4);方法二:
Insert into T values(1,2),(1,3),(1,4);选择后一种方法的原因有三:

  • 减少 SQL 语句解析的操作 , MySQL 没有类似 Oracle 的 share pool , 采用方法二 , 只需要解析一次就能进行数据的插入操作 。
  • 在特定场景可以减少对 DB 连接次数 。
  • SQL 语句较短 , 可以减少网络传输的 IO 。
②适当使用 commit
适当使用 commit 可以释放事务占用的资源而减少消耗 , commit 后能释放的资源如下:
  • 事务占用的 undo 数据块 。
  • 事务在 redo log 中记录的数据块 。
  • 释放事务施加的 , 减少锁争用影响性能 。 特别是在需要使用 delete 删除大量数据的时候 , 必须分解删除量并定期 commit 。
③避免重复查询更新的数据
针对业务中经常出现的更新行同时又希望获得改行信息的需求 , MySQL 并不支持 PostgreSQL 那样的 UPDATE RETURNING 语法 , 在 MySQL 中可以通过变量实现 。
例如 , 更新一行记录的时间戳 , 同时希望查询当前记录中存放的时间戳是什么?
简单方法实现:
Update t1 set time=now() where col1=1; Select time from t1 where id =1;使用变量 , 可以重写为以下方式:
Update t1 set time=now () where col1=1 and @now: = now (); Select @now;前后二者都需要两次网络来回 , 但使用变量避免了再次访问数据表 , 特别是当 t1 表数据量较大时 , 后者比前者快很多 。
④查询优先还是更新(insert、update、delete)优先
MySQL 还允许改变语句调度的优先级 , 它可以使来自多个客户端的查询更好地协作 , 这样单个客户端就不会由于锁定而等待很长时间 。 改变优先级还可以确保特定类型的查询被处理得更快 。
我们首先应该确定应用的类型 , 判断应用是以查询为主还是以更新为主的 , 是确保查询效率还是确保更新的效率 , 决定是查询优先还是更新优先 。
下面我们提到的改变调度策略的方法主要是针对只存在表锁的存储引擎 , 比如 MyISAM 、MEMROY、MERGE , 对于 Innodb 存储引擎 , 语句的执行是由获得行锁的顺序决定的 。
MySQL 的默认的调度策略可用总结如下:
  • 写入操作优先于读取操作 。
  • 对某张数据表的写入操作某一时刻只能发生一次 , 写入请求按照它们到达的次序来处理 。
  • 对某张数据表的多个读取操作可以同时地进行 。
MySQL 提供了几个语句调节符 , 允许你修改它的调度策略:
  • LOW_PRIORITY 关键字应用于 DELETE、INSERT、LOAD DATA、REPLACE 和 UPDATE 。
  • HIGH_PRIORITY 关键字应用于 SELECT 和 INSERT 语句 。
  • DELAYED 关键字应用于 INSERT 和 REPLACE 语句 。
如果写入操作是一个 LOW_PRIORITY(低优先级)请求 , 那么系统就不会认为它的优先级高于读取操作 。
在这种情况下 , 如果写入者在等待的时候 , 第二个读取者到达了 , 那么就允许第二个读取者插到写入者之前 。
只有在没有其它的读取者的时候 , 才允许写入者开始操作 。 这种调度修改可能存在 LOW_PRIORITY 写入操作永远被阻塞的情况 。
SELECT 查询的 HIGH_PRIORITY(高优先级)关键字也类似 。 它允许 SELECT 插入正在等待的写入操作之前 , 即使在正常情况下写入操作的优先级更高 。
另外一种影响是 , 高优先级的 SELECT 在正常的 SELECT 语句之前执行 , 因为这些语句会被写入操作阻塞 。


推荐阅读