DISTINCT 列添加索引

本文探讨了在SQL查询中使用DISTINCT进行数据去重时,为相关列添加索引的效果。实验结果显示,尽管索引对全表扫描的影响不大,但在大量数据处理时,仍需考虑其他优化策略,如基表关联和业务逻辑审查。
添加索引后,没啥效要,这方面优化没啥效果,如果项目要用到DISTINCT进行去重,需要再去确认基表关联,确认业务。

SQL> select t.object_id from t_distinct_tb t ;

已选择50631行。

已用时间:  00: 00: 00.71

执行计划
----------------------------------------------------------
Plan hash value: 1512865825

-----------------------------------------------------------------------------------
| Id  | Operation         | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |               | 50086 |   635K|   161   (2)| 00:00:02 |
|   1 |  TABLE ACCESS FULL| T_DISTINCT_TB | 50086 |   635K|   161   (2)| 00:00:02 |
-----------------------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement


统计信息
----------------------------------------------------------
         50  recursive calls
          0  db block gets
       4109  consistent gets
        696  physi
<think>我们之前已经创建了employee表,现在需要为其添加索引以提高查询性能。常见的查询条件字段包括name和department,索引可以速WHERE子句、JOIN操作和ORDER BY排序等。 考虑到员工表可能经常按姓名查询,按部门查询,或者按薪资范围查询,我们可以为这些字段创建索引。 注意: 1. 主键id已经有聚集索引(InnoDB引擎),不需要额外创建。 2. 索引虽然提高查询速度,但会降低写入速度(因为需要维护索引),并且占用额外空间。 以下是几种索引创建方式: 1. 单索引:在单个上创建索引。 2. 组合索引:在多个上创建索引,适合多条件查询。 例如: 如果经常按name查询,可以创建name的索引。 如果经常同时按department和salary范围查询,可以创建(department, salary)的组合索引。 根据需求,我们为name和department分别创建单索引(如果查询条件经常单独使用这两个字段)。另外,如果经常使用department和salary一起查询,可以额外创建一个组合索引。 但注意:不要过度索引,因为每个额外的索引都会增更新操作的开销。 下面给出为employee表添加索引的SQL语句: 1. 为name字段添加索引(因为name可能用于精确查询或模糊查询,如果是精确查询,索引有效;如果是前模糊查询,如'%John',则索引无效): ```sql CREATE INDEX idx_employee_name ON employee(name); ``` 2. 为department字段添加索引: ```sql CREATE INDEX idx_employee_department ON employee(department); ``` 3. 如果经常同时根据department和salary进行查询(例如:查询某个部门薪资大于某个值的员工),可以创建组合索引: ```sql CREATE INDEX idx_employee_dep_salary ON employee(department, salary); ``` 注意:组合索引的顺序很重要。应将最常用于查询条件的放在前面,并且考虑的区分度(cardinality)。通常,区分度高的放在前面。 另外,对于包含ORDER BY的查询,索引的顺序也很重要。例如,如果查询某部门的员工并按薪资排序,那么组合索引(department, salary)可以同时用于过滤和排序。 示例:查询HR部门薪资大于5000的员工并按薪资排序 ```sql SELECT * FROM employee WHERE department='HR' AND salary>5000 ORDER BY salary; ``` 这个查询就可以利用组合索引idx_employee_dep_salary,因为索引已经按department和salary排序,可以快速定位部门并利用索引的顺序避免额外排序。 除了普通索引,还有唯一索引(唯一约束)、全文索引(全文搜索)等,但这里我们只需要普通索引索引创建后,可以使用EXPLAIN语句分析查询是否使用了索引。 例如: ```sql EXPLAIN SELECT * FROM employee WHERE name='John Doe'; ``` 输出结果中,key会显示使用的索引名。 总结:索引是提高查询性能的关键,但需要根据实际查询模式来设计。 §§相关问题§§: 1. 如何判断是否需要为某个字段创建索引? 2. 组合索引的最左前缀原则是什么? 3. 索引对插入和更新操作的性能有什么影响? 4. 在MySQL中如何查看一个表的索引? </think>### 如何为 employee 表添加索引以提高查询性能 #### 索引类型及适用场景 | 索引类型 | 适用场景 | 优势 | 缺点 | |----------|----------|------|------| | **单索引** | WHERE 条件中的单筛选 | 简单高效,维护成本低 | 不适合多组合查询 | | **复合索引** | 多组合查询和排序 | 覆盖多个查询条件,优化排序 | 顺序影响效率 | | **唯一索引** | 保证值唯一性 | 强制唯一性约束,优化查找 | 不适合允许重复值的 | | **前缀索引** | 长文本字段(如VARCHAR(255)) | 减少索引存储空间 | 可能降低查询精度 | #### 索引创建代码示例 ##### 1. 创建单索引(优化 name 查询) ```sql -- 为 name 创建普通索引 CREATE INDEX idx_name ON employee(name); -- 为 salary 创建索引(优化薪资范围查询) CREATE INDEX idx_salary ON employee(salary); ``` ##### 2. 创建复合索引(优化 department + salary 查询) ```sql -- 优化部门薪资联合查询(部门优先) CREATE INDEX idx_department_salary ON employee(department, salary); -- 优化薪资部门联合查询(薪资优先) CREATE INDEX idx_salary_department ON employee(salary, department); ``` **复合索引使用要点**: - 遵循最左前缀原则:`WHERE department = 'HR' AND salary > 5000` 可使用索引 - `WHERE salary > 5000` 无法使用 `idx_department_salary` 索引(部门缺失) ##### 3. 创建唯一索引(确保 email 唯一) ```sql ALTER TABLE employee ADD email VARCHAR(255) UNIQUE; -- 为 email 创建唯一索引 CREATE UNIQUE INDEX idx_unique_email ON employee(email); ``` ##### 4. 创建前缀索引(优化长文本 department 字段) ```sql -- 取 department 前 20 个字符创建索引 CREATE INDEX idx_department_prefix ON employee(department(20)); ``` #### 索引优化建议 1. **优先为 WHERE/JOIN/ORDER BY 涉及的创建索引** 2. **遵循复合索引的最左前缀原则**:将高区分度放左侧 ```sql -- 区分度计算示例 SELECT COUNT(DISTINCT department)/COUNT(*) AS department_distinct, COUNT(DISTINCT salary)/COUNT(*) AS salary_distinct FROM employee; ``` 3. **避免过度索引**:每个额外索引 5-20% 的写操作开销 4. **定期分析索引使用情况**: ```sql -- 查看索引使用统计 SELECT * FROM sys.schema_index_statistics WHERE table_name = 'employee'; -- 优化后使用 EXPLAIN 验证 EXPLAIN SELECT * FROM employee WHERE department = 'HR' AND salary > 5000; ``` #### 完整索引优化示例 ```sql -- 添加新字段 ALTER TABLE employee ADD email VARCHAR(255); -- 创建复合索引(部门+薪资) CREATE INDEX idx_dep_sal ON employee(department, salary); -- 创建唯一索引 CREATE UNIQUE INDEX idx_unique_email ON employee(email); -- 创建前缀索引(部门名称前10字符) CREATE INDEX idx_dep_prefix ON employee(department(10)); -- 查询优化验证 EXPLAIN SELECT id, name FROM employee WHERE department = 'Engineering' AND salary BETWEEN 6000 AND 8000; ``` **执行计划关键指标解读**: - `type: ref` 表示索引查找 - `key: idx_dep_sal` 显示使用的索引 - `rows: 1` 表示扫描行数少(高效) - `Extra: Using index` 表示覆盖索引(无需回表)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值