在select 中的where 中使用index

本文通过对比测试,在Oracle数据库中展示了创建索引前后的查询性能差异。实验表明,合理使用索引能够显著提高特定条件下的查询速度,从原来的4.46秒减少到0.01秒。

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

/* 2008/07/01 星期一
*蒙昭良
*环境:windowsXP + Oracle10gR2
*在select 中的where 中使用index
*/
1 在where中使用索引
SQL> set timing on
SQL> set autotrace on
SQL> drop index test_owner_index;

索引已删除。

已用时间:  00: 00: 02.01

没有使用索引之前:全表扫描花4.46秒
SQL> select count(*) from test where wner='RISENET';

  COUNT(*)                                                                     
----------                                                                     
      1350                                                                     

已用时间:  00: 00: 04.46

执行计划
----------------------------------------------------------                     
Plan hash value: 1950795681                                                    
                                                                               
---------------------------------------------------------------------------    
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |    
---------------------------------------------------------------------------    
|   0 | SELECT STATEMENT   |      |     1 |     6 |  4110   (1)| 00:00:50 |    
|   1 |  SORT AGGREGATE    |      |     1 |     6 |            |          |    
|*  2 |   TABLE ACCESS FULL| TEST |  1052 |  6312 |  4110   (1)| 00:00:50 |    
---------------------------------------------------------------------------    
                                                                               
Predicate Information (identified by operation id):                            
---------------------------------------------------                            
                                                                               
   2 - filter("OWNER"='RISENET')                                               


统计信息
----------------------------------------------------------                     
        124  recursive calls                                                   
          0  db block gets                                                     
      15108  consistent gets                                                   
      15087  physical reads                                                    
          0  redo size                                                         
        409  bytes sent via SQL*Net to client                                  
        385  bytes received via SQL*Net from client                            
          2  SQL*Net roundtrips to/from client                                 
          2  sorts (memory)                                                    
          0  sorts (disk)                                                      
          1  rows processed                                                    

SQL> create index test_owner_index
  2  on test(owner);

索引已创建。

已用时间:  00: 00: 04.57

使用索引之后:0.01秒

SQL> select count(*) from test where wner='RISENET';

  COUNT(*)                                                                     
----------                                                                     
      1350                                                                     

已用时间:  00: 00: 00.01

执行计划
----------------------------------------------------------                     
Plan hash value: 1335201336                                                    
                                                                               
--------------------------------------------------------------------------------
------                                                                         
                                                                               
| Id  | Operation         | Name             | Rows  | Bytes | Cost (%CPU)| Time
     |                                                                         
                                                                               
--------------------------------------------------------------------------------
------                                                                         
                                                                               
|   0 | SELECT STATEMENT  |                  |     1 |     6 |     3   (0)| 00:0
0:01 |                                                                         
                                                                               
|   1 |  SORT AGGREGATE   |                  |     1 |     6 |            |    
     |                                                                         
                                                                               
|*  2 |   INDEX RANGE SCAN| TEST_OWNER_INDEX |  1052 |  6312 |     3   (0)| 00:0
0:01 |                                                                         
                                                                               
--------------------------------------------------------------------------------
------                                                                         
                                                                               
                                                                               
Predicate Information (identified by operation id):                            
---------------------------------------------------                            
                                                                               
   2 - access("OWNER"='RISENET')                                               


统计信息
----------------------------------------------------------                     
          1  recursive calls                                                   
          0  db block gets                                                     
          6  consistent gets                                                   
          5  physical reads                                                    
          0  redo size                                                         
        409  bytes sent via SQL*Net to client                                  
        385  bytes received via SQL*Net from client                            
          2  SQL*Net roundtrips to/from client                                 
          0  sorts (memory)                                                    
          0  sorts (disk)                                                      
          1  rows processed                                                    

SQL> spool off
 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/12778571/viewspace-368744/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/12778571/viewspace-368744/

<think>好的,用户之前问过关于RMySQL中执行SELECT语句的过程,现在他想了解MySQL本身中SELECT语句的执行过程。我需要从底层机制来详细说明,而不是R语言包的部分。 首先,用户可能是数据库开发人员或数据分析师,想要优化查询性能或者理解内部工作原理。他可能遇到了性能问题,需要知道查询是如何被处理的,以便进行调优。 接下来,我需要回顾MySQL执行SELECT语句的步骤。通常包括解析器、优化器、执行引擎等部分。要分阶段详细解释,比如语法分析、查询优化、执行计划生成、数据读取、返回结果等。 同时,用户可能对索引的使用、锁机制、缓存这些方面感兴趣,这些是优化查询的关键点。需要提到InnoDB的架构,比如Buffer Pool、Redo Log等,说明它们如何影响查询性能。 另外,用户之前的回答中提到了RMySQL的注意事项,现在需要专注于MySQL本身,可能需要对比之前的回答,避免重复,而是深入MySQL内部机制。 还要注意用户可能的深层需求,比如如何避免慢查询,如何分析执行计划,或者事务隔离级别的影响。需要涵盖这些方面,给出实际例子或建议。 最后,确保语言通俗易懂,结构清晰,分步骤说明,可能用列表或流程图的方式帮助理解。检查是否有遗漏的重要环节,比如查询缓存(虽然MySQL 8.0已经移除了),或者存储引擎的不同处理方式。</think>在 MySQL 中,一条 `SELECT` 语句的执行过程涉及多个组件的协同工作,其底层实现可以分为以下几个核心阶段: --- ### **一、SQL 语句解析阶段** 1. **词法分析(Lexer)** - 将 `SELECT * FROM users WHERE id = 1` 拆解为 `SELECT`、`*`、`FROM` 等词法单元(Token) - 检测基本语法错误(如缺少关键字) 2. **语法分析(Parser)** - 根据 SQL 语法规则构建抽象语法树(AST) - 验证表名、列名是否存在(*不访问实际数据,仅检查元数据*) 3. **预处理(Preprocessor)** - 解析别名和表达式(如 `SELECT id AS user_id`) - 展开视图(View)和优化常量表达式(如 `WHERE 1=1`) --- ### **二、查询优化阶段** 1. **逻辑优化** - **子查询优化**:将 `IN (SELECT ...)` 改写为 `JOIN` - **谓词下推**:将过滤条件尽可能下推到存储引擎层(如 InnoDB) - **常量传播**:替换可推导的常量(如 `WHERE id = 10-5` → `WHERE id = 5`) 2. **物理优化** - **成本估算**:基于统计信息(`SHOW TABLE STATUS`)计算不同执行计划的成本 - **索引选择**:决定使用全表扫描(`ALL`)或索引扫描(`INDEX`/`REF`) - **连接顺序优化**:调整多表连接的顺序(如小表驱动大表) --- ### **三、执行引擎阶段** 1. **执行计划生成** - 生成查询计划树(可通过 `EXPLAIN FORMAT=TREE` 查看) - 示例: ``` -> Nested loop inner join -> Index lookup on users using PRIMARY (id=1) -> Filter: (users.age > 18) ``` 2. **数据读取与过滤** - **存储引擎交互**:通过 `Handler API` 调用存储引擎(如 InnoDB) - **行数据解析**:从数据页中读取行,根据 `WHERE` 条件过滤不符合的行 3. **结果集构建** - **排序(Sort)**:若包含 `ORDER BY`,可能在内存或磁盘进行排序 - **聚合(Aggregation)**:执行 `GROUP BY` 或聚合函数(`SUM`/`COUNT`) - **去重(Distinct)**:通过临时表或哈希算法实现 `DISTINCT` --- ### **四、关键组件协作** 1. **Buffer Pool** - InnoDB 的内存缓存池,缓存热数据页,减少磁盘 IO - 数据页读取顺序:Buffer Pool → 磁盘(若未命中) 2. **Undo Log & MVCC** -写不阻塞 - 使用 Undo Log 构造一致性视图(Consistent Read View) 3. **锁机制** - 根据隔离级别(如 `REPEATABLE READ`)决定是否加锁 - 示例:`SELECT ... FOR UPDATE` 会对行加排他锁(X Lock) --- ### **五、性能调优要点** 1. **索引设计** - 覆盖索引(Covering Index):避免回表(`Using index`) - 索引下推(ICP):在存储引擎层过滤数据(`Using index condition`) 2. **执行计划分析** - 使用 `EXPLAIN` 关注以下字段: - `type`:访问类型(`const` > `ref` > `range` > `index` > `ALL`) - `Extra`:`Using filesort` 或 `Using temporary` 表示需优化 3. **参数调整** - `read_buffer_size`:控制排序和全表扫描的缓冲区大小 - `optimizer_switch`:启用/禁用特定优化策略(如 `batched_key_access=on`) --- ### **六、典型执行流程示例** 以 `SELECT * FROM users WHERE id = 1` 为例: 1. 客户端通过 MySQL 协议发送查询到服务端 2. 解析器生成语法树,优化器选择主键(PRIMARY)索引 3. InnoDB 通过 B+树定位 `id=1` 的数据页(可能在 Buffer Pool 中) 4. 返回行数据到 Server 层,构建结果集 5. 结果集通过网络协议返回客户端 --- ### **七、高级特性** 1. **并行查询(MySQL 8.0+)** - 对分区表或大表扫描启用多线程(`innodb_parallel_read_threads`) 2. **直方图统计(Histogram Statistics)** - 将查询绑定到特定 CPU 核,控制资源分配(需企业版) --- 通过理解这些底层机制,可以更高效地设计索引、分析慢查询和优化数据库性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值