DDL 索引

http://www.verejava.com/?id=1717413695356

1 . 索引
  索引(index) 是提升查询效率的数据库对象.
  
  
  2. 索引分类
    1. 唯一性索引和非唯一性索引
      按照索引字段是否允许重复来划分的,  一般唯一性索引查询效率最高, 所以MySQL 给主键和唯一键自动分配唯一性索引.
  
    2. 单索引和联合索引
      按照索引基于字段的个数来划分. 例如 :如果我们经常在 工资 和 部门编号 经常执行下面的查询 . 可以在 salary 和 dept_id 建立联合索引
      SELECT * FROM emp WHERE salary<=6000 AND dept_id=1;
  
    3. 普通索引和函数索引
      前面讲的是普通索引 如果我们索引是基于表的字段, 常量, 函数和运算构成的表达式,叫做函数索引.
      例如 经常执行 以字母 l 开头的人查询出来     这样就要建立  SUBSTR(name,0,1) 的函数索引
      SELECT * FROM emp WHERE SUBSTR(name,0,1)='l';
      
    
    准备数据:
    DROP TABLE emp;
    创建表 emp
    CREATE TABLE emp
      (
      id int(10),
      name VARCHAR(30),
      salary int(10),
      sex  CHAR(2),
      dept_id int(10),
      FOREIGN KEY (dept_id) REFERENCES dept(id) 
      );
    批量插入数据
    INSERT INTO emp VALUES(1,'王浩',6000,'女',1);
    INSERT INTO emp VALUES(2,'王丽',5000,'女',1);
    INSERT INTO emp VALUES(3,'李俊',4000,'男',2);
    INSERT INTO emp VALUES(4,'张涛',8000,'男',2);
    INSERT INTO emp VALUES(5,'李广',9000,'男',2);
    INSERT INTO emp VALUES(6,'杨军',7000,'男',2);
      
  
  3. 创建索引
    CREATE [UNIQUE | BITMAP] INDEX 索引名 ON table(列名 ...);
  
    例子:
      创建基于 name 字段的 普通索引
      CREATE INDEX name_index ON emp(name);
  
      创建基于 dept_id 和 salary 的联合索引
      CREATE INDEX deptid_salary_index ON emp(dept_id,salary);
  
      创建基于 id 的唯一索引
      CREATE UNIQUE INDEX id_unique_index ON emp(id);
  
      创建基于 dept_id 的位图索引
      CREATE BITMAP INDEX dept_bitmap_index ON emp(sex);
  
      创建函数索引
      CREATE INDEX name_function_index ON emp(SUBSTR(name,0,1)); 
  
      查看表建立的所有索引
      SELECT index_name,index_type FROM user_indexes WHERE table_name='EMP';
  
      查看表的索引具体建立在那个字段
      SELECT index_name,column_name FROM user_ind_columns WHERE table_name='EMP';
  
      注意:
        如果索引一旦建立了, 就会由MySQL数据库字段维护, 当对表的数据(INSERT , DELETE, UPDATE,MERGE) 时系统必须同步修改 索引表的数据, 
        所以在表的数据量很大, 更新频率很多的时候要谨慎使用索引, 不然适得其反.
  
  4. 创建索引的原则
    下列情况适合创建索引:
    1. 字段取值分布范围很广
    2. 字段中包含大量空值
    3. 字段经常出现在 where 子句 或 连接条件中
    4. 表经常被访问, 数据量很大, 一般每次访问的数据量 < 5%
      
    下列情况不适合创建索引
    1. 表很小
    2. 字段不经常出现在 where 子句中
    3. 每次访问的数据量 > 5%
    4. 表经常更新
      
  5. 删除索引
    索引一旦创建不可再修改, 如果要修改必须删除掉然后重新创建.
    在删除表和字段时 在该表和字段上创建的索引自动删除.
    DROP INDEX 索引名

http://www.verejava.com/?id=1717413695356

### DDL 添加索引后导致查询锁表的原因 在 MySQL 中,当执行 `ALTER TABLE ... ADD INDEX` 这类 DDL 操作时,可能会触发元数据锁(Metadata Lock, MDL),从而影响其他查询的操作。具体来说: - 当一个会话正在对某个表进行 DDL 操作(如添加索引)时,该操作会对目标表施加一种独占性的元数据锁[^3]。这种锁阻止了其他任何读写操作对该表的访问,直到 DDL 完成为止。 - 如果另一个会话在此期间尝试对该表发起查询或其他操作,则这些请求会被阻塞并等待锁释放,表现为 “Waiting for table metadata lock” 的状态。 此外,在某些情况下,如果存在未提交的事务持有共享锁或排他锁,也会进一步加剧这种情况的发生概率[^2]。 ### 解决方案 针对上述问题可以采取以下几种措施来缓解或者避免因 DDL索引起锁表现象: #### 方法一:使用 Online DDL 功能 从 MySQL 5.6 开始引入了 Online DDL 特性,允许部分类型的 ALTER TABLE 操作能够在不完全锁定整个表格的情况下完成。对于增加次级索引这样的变更,默认就是在线模式,即不会阻碍正常的增删改查业务流程[^1]。 不过需要注意的是,并非所有的修改都支持 online 方式;而且即使启用了此功能,也可能因为硬件资源不足等原因退化为传统离线方式处理。因此建议提前确认版本兼容性和实际运行环境配置情况后再实施计划内的结构调整动作。 以下是启用 Online DDL 的语法实例: ```sql -- 显式指定 ALGORITHM 和 LOCK 参数以确保最小干扰程度 ALTER TABLE your_table_name ADD INDEX idx_column_name(column_name), ALGORITHM=INPLACE, LOCK=NONE; ``` #### 方法二:分批次更新大数据量表 如果是面对特别庞大的数据库对象做改动的话,考虑到性能损耗因素,可以选择拆分成更小单元逐步推进策略而不是一次性全盘改造完毕。比如先复制源表创建新副本再交换名称替代原位置等手段间接达成目的同时减少即时冲击力道。 下面给出一段伪代码用于演示如何通过临时过渡表实现无缝迁移过程: ```sql CREATE TEMPORARY TABLE temp_your_table LIKE your_table; INSERT INTO temp_your_table SELECT * FROM your_table WHERE MOD(id, N) = M; -- 根据需求筛选子集填充至暂存区 RENAME TABLE your_table TO old_your_table, temp_your_table TO your_table; DROP TABLE IF EXISTS old_your_table; ``` > 注释中的变量N代表分区总数目,M表示当前片段编号(范围应介于0~N-1之间) #### 方法三:优化应用层逻辑设计 最后还可以考虑从业务层面出发重新审视现有架构是否存在可改进空间进而降低对外部依赖强度达到相同效果却无需频繁触碰底层物理存储布局的目的。例如合理设置连接池大小参数控制并发度上限防止过度竞争公共资源造成拥堵瓶颈等问题发生几率提升整体吞吐能力表现水平等等诸多方面均值得深入探讨研究一番才行呢! ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值