mysql如何加索引的时候不锁表

本文详细介绍了在MySQL中在线修改表索引时使用的ALGORITHM和LOCK参数。ALGORITHM=INPLACE是在不复制数据的情况下直接在原表上添加索引,而ALGORITHM=COPY则涉及数据的复制和临时表。LOCK参数提供了不同级别的锁定策略,如NONE允许并发读写,SHARED阻塞写入但允许读取,EXCLUSIVE则完全锁定表。理解这些参数对于优化数据库操作和减少业务影响至关重要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

场景
因为公司业务需要,之前的容器只有一种,所以就直接叫了lotCarId,但是因为后来业务中添加了另一种容器,于是大佬们决定使用一个type作为区分,然后因为都是容器,于是加了一个字段containerId,并且查询都是走containerId,于是之前线上的表的lotCarId就没用了.
现需要修改表的索引,但是为了不锁表,于是sql需要添加两个参数.
ALGORITHM=INPLACELOCK = NONE

ALTER TABLE `tableName`
ADD INDEX idx_container_id(container_id) USING BTREE ,
ALGORITHM=INPLACE, LOCK = NONE;

分析
下面分别分析下这两个参数的意义:

ALGORITHM=INPLACE
更优秀的解决方案,在当前表加索引,步骤:
1.创建索引(二级索引)数据字典
2.加共享表锁,禁止DML,允许查询
3.读取聚簇索引,构造新的索引项,排序并插入新索引
4.等待打开当前表的所有只读事务提交
5.创建索引结束
 
ALGORITHM=COPY
通过临时表创建索引,需要多一倍存储,还有更多的IO,步骤:
1.新建带索引(主键索引)的临时表
2.锁原表,禁止DML,允许查询
3.将原表数据拷贝到临时表
4.禁止读写,进行rename,升级字典锁
5.完成创建索引操作
 
LOCK=DEFAULT:默认方式,MySQL自行判断使用哪种LOCK模式,尽量不锁表
LOCK=NONE:无锁:允许Online DDL期间进行并发读写操作。如果Online DDL操
作不支持对表的继续写入,则DDL操作失败,对表修改无效
LOCK=SHARED:共享锁:Online DDL操作期间堵塞写入,不影响读取
LOCK=EXCLUSIVE:排它锁:Online DDL操作期间不允许对锁表进行任何操作

参考链接: https://blog.csdn.net/fujian9544/article/details/106462274

<think>好的,用户的问题是关于PostgreSQL在生产环境中已有大量数据的新增索引时遇到耗时过长的问题,需要解决办法。首先,我需要回忆一下PostgreSQL索引创建的相关知识,特别是处理大时的优化方法。 首先,用户遇到的问题可能是因为创建索引需要扫描整个并写入新的索引结构,对于大来说这确实很耗时。可能的解决办法包括使用CONCURRENTLY关键字,这样可以在创建索引阻塞读写操作,但会增一些时间和资源消耗。另外,考虑索引的类型是否合适,比如B-tree是否适用于查询条件,或者是否有必要创建复合索引。还有,是否可以在业务低峰期创建索引,减少对生产的影响。此外,检查是否有其他长时间运行的事务阻塞了索引创建,或者是否有未提交的事务导致竞争。另外,可能需要调整PostgreSQL的配置参数,比如work_mem,增临时内存以索引构建速度,但需要注意要超过系统内存限制。还有,分批次创建索引,比如使用部分索引(Partial Index)只对符合条件的数据创建索引,减少索引大小。或者,先创建唯一索引的话,可能需要检查是否有重复值,避免创建失败。另外,分析的统计信息是否最新,ANALYZE是否需要先执行,确保查询优化器有足够信息。 现在需要把这些思路整理成有条理的解决办法。首先,最常用的方法是使用CREATE INDEX CONCURRENTLY,这样会阻塞的读写,但需要注意该操作能在事务块中执行,且需要更长时间。其次,调整索引策略,比如部分索引或覆盖索引,减少索引数据量。然后,选择业务低峰期执行,减少对在线服务的影响。另外,检查是否有长事务阻塞,使用pg_locks视图查看情况,终止必要的长事务。还可以调整配置参数,如maintenance_work_mem,增索引构建时的内存使用,快速度。此外,如果索引是唯一的,先检查是否有重复值,避免创建失败。最后,如果非常大,可能考虑重建,比如使用CTAS(Create Table As Select)创建新并添索引,然后重命名切换,但需要停机时间。 现在需要将这些方法组织成用户容易理解的步骤,并确保覆盖主要的解决方向。然后,根据问题和回答,生成相关的问题,比如关于CONCURRENTLY的注意事项、部分索引的使用场景、配置参数调整的影响、如何检查长事务、CTAS方法的具体步骤等。 </think>在PostgreSQL生产环境中对大新增索引耗时过长时,可尝试以下解决方法: ### 1. 使用`CONCURRENTLY`关键字创建索引(推荐) 默认创建索引时会阻塞的写操作(如`INSERT/UPDATE/DELETE`),且可能长时间持有。通过`CREATE INDEX CONCURRENTLY`可在阻塞读写的情况下异步构建索引(需注意:此操作能在事务块内执行,且耗时可能比普通索引更长,但对生产影响最小)。 示例: ```sql CREATE INDEX CONCURRENTLY idx_your_table_column ON your_table (column); ``` ### 2. 选择业务低峰期执行 大索引创建需要扫描全并写入磁盘,会占用大量I/O和CPU资源。选择业务流量最低的时间段执行(如凌晨),可减少对在线服务响应的影响。 ### 3. 优化索引策略 - **部分索引(Partial Index)**:若仅需对部分数据创建索引(如只针对“未删除”的记录),可通过`WHERE`条件限制索引范围,减少索引大小和构建时间。 示例: ```sql CREATE INDEX idx_active_users ON users (email) WHERE is_deleted = false; ``` - **覆盖索引(Covering Index)**:若查询仅需索引中的列(无需回),可通过`INCLUDE`包含额外列,避免全扫描,同时可能减小索引构建压力(需评估必要性)。 示例: ```sql CREATE INDEX idx_orders ON orders (user_id) INCLUDE (order_amount); ``` ### 4. 调整PostgreSQL配置参数 增大`maintenance_work_mem`参数(默认64MB),为索引构建分配更多内存,减少磁盘临时文件的使用,快速度。注意:该参数仅对当前会话或单个操作生效,需重启数据库或通过`SET`临时调整(需确保服务器内存充足)。 示例: ```sql SET maintenance_work_mem = '2GB'; -- 根据服务器内存调整 CREATE INDEX idx_your_table_column ON your_table (column); ``` ### 5. 检查长事务或阻塞 通过`pg_locks`视图检查是否有长事务或竞争阻塞了索引创建(如未提交的事务持有)。终止必要的长事务后重新尝试。 示例查询: ```sql SELECT * FROM pg_locks WHERE relation = 'your_table'::regclass; ``` ### 6. 重建(极端情况) 若数据量极大且索引必须快速生效,可通过`CREATE TABLE AS SELECT`(CTAS)创建新(自动继承原结构但无索引),为新快速添索引后,通过`RENAME`切换名(需短暂停机,适合对可用性要求高的场景)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值