删除
删除未在他表出现的数据
下面有一条效率较差的删除语句,主要功能是将t1表中id未出现在t2表的记录删除。效率差的原因是in中用了子查询,导致删除语句不会走索引,从而导致锁全表,继而导致删除效率差。
|
|
优化方法:取消子查询,改用关联删除,这样就可以使用建在id列上的索引。关联删除/更新在建立索引的情况下效率远高于in/exists
优化后的SQL语句如下:
|
|
注:上面这条是MySQL独有的优化,达梦数据库和Oracle中可用如下语句。(拾人牙慧,未经验证,用这两个数据库的朋友可以自行验证一下)(+)
表示单侧关联,该符号在哪边哪边就是副表。
|
|
删除多表相同数据
好的删除语句如下:
|
|
这样可以同时删除从主从表删除。比如一条记录记录在多张表中,删除这条记录需要同时删除两张表的记录。这样可以保证要么全部删除,要么全部不删,间接满足了事务一致性。(数据库只会从一个状态转移至另外一个状态,即拥有这条记录和没有这条记录的两个状态。这一条记录可以看成是一个入库记录、一张支票)
删除全表数据
用truncate替代delete。这里涉及delete的机制,delete并不是直接在磁盘中删除记录,而是将记录加一个标记,并设置为不可见,然后在数据库压力小时异步删除磁盘中的数据。但是这样有一个问题,虽然标记为删除后,查询表记录不可见。但是记录仍然占有着磁盘空间,这会拖慢查询数据库的速度。
|
|
更新
差的更新语句如下:
|
|
如删除篇中所说,由于in中属性过多,in不会再走索引(当属性值大于4个后就不会再走索引,in中是子查询的话就不会走索引)。所以这里的更新效率慢,并且还会锁住整表。
关于为什么全表扫描会锁住整张表可以看小林的教程:update 没加索引会锁全表?
优化方式:
- 创建id临时表,临时表只有id一个字段
- 批量插入临时表,记录为上面差的更新语句中的记录,也即是需要更新的记录的id
- 将临时表于原表关联更新
补充:插入更新
插入一条数据,如果存在主键或唯一键冲突,则更新记录
注:使用此语句时,必须在表中定义主键或唯一约束
|
|
例如:
|
|
PostgreSQL中用法如下:
|
|
如果想同时修改多个字段也可用下面的写法
|
|
如果想遇见冲突主键不做处理可用如下语句
|
|