从简单到专业在OceanBase中查看SQL是否走索引

在OceanBase中,查看SQL是否走索引最直接的方法就是分析执行计划。以下是详细的操作步骤,从简单到专业,帮你彻底掌握这个技能。

一、核心判断方法:分析执行计划

第1步:获取SQL的执行计划

使用EXPLAIN命令查看SQL的执行计划,这是最关键的一步:

sql

复制代码
-- 方法1:基础执行计划(快速判断)
EXPLAIN SELECT * FROM users WHERE user_id = 1001;

-- 方法2:详细执行计划(推荐,信息更全)
EXPLAIN EXTENDED SELECT * FROM orders WHERE customer_id = 200 AND amount > 1000;

-- 方法3:JSON格式(最详细,适合复杂分析)
EXPLAIN FORMAT = JSON SELECT * FROM products WHERE category = 'electronics' AND price < 500;

第2步:解读执行计划中的关键信息

查看执行计划输出,重点关注以下两点:

1. 看OPERATOR列:

  • 如果显示 TABLE SCAN没有走索引,正在全表扫描

  • 如果显示 INDEX SCANINDEX SEEK走了索引

  • 如果显示 TABLE GET → 通常是通过主键等值访问,也属于索引访问的一种

2. 看NAME列:

  • 如果NAME显示 表名(别名)users(t1) → 全表扫描

  • 如果NAME显示 表名(别名)索引名users(t1),idx_user_id → 使用了名为idx_user_id的索引

第3步:实际案例对比

案例1:没有走索引的情况

sql

复制代码
EXPLAIN SELECT * FROM employees WHERE email = 'zhangsan@company.com';

输出可能类似:

text

复制代码
==================================================
|ID|OPERATOR   |NAME          |EST. ROWS|COST   |
--------------------------------------------------
|0 |TABLE SCAN |employees(emp)|1        |1056   |
==================================================

结论 :看到TABLE SCAN,说明没有走索引,进行了全表扫描。

案例2:走了索引的情况

sql

复制代码
-- 假设在user_id上有索引
EXPLAIN SELECT * FROM users WHERE user_id = 1001;

输出可能类似:

text

复制代码
=======================================================
|ID|OPERATOR    |NAME                 |EST. ROWS|COST |
-------------------------------------------------------
|0 |TABLE GET   |users(u)             |1        |53   |
=======================================================

或者:

text

复制代码
===============================================================
|ID|OPERATOR    |NAME                     |EST. ROWS|COST    |
---------------------------------------------------------------
|0 |INDEX SCAN  |users(u),idx_user_id     |1        |46      |
|1 | TABLE GET  |users(u)                 |1        |53      |
===============================================================

结论 :看到INDEX SCANTABLE GET(通过主键访问),说明走了索引。

二、进阶诊断:为什么没走索引?

如果发现SQL没走索引,可以按以下步骤排查:

第1步:检查表上是否存在相关索引

sql

复制代码
-- 查看表的索引信息
SHOW INDEX FROM 表名;

-- 或使用更详细的查询
SELECT 
    table_name,
    index_name,
    column_name,
    seq_in_index
FROM information_schema.statistics 
WHERE table_schema = '你的数据库名'
AND table_name = '你的表名'
ORDER BY index_name, seq_in_index;

第2步:检查索引是否适合当前查询

sql

复制代码
-- 查看表的创建语句,了解索引结构
SHOW CREATE TABLE 表名;

常见问题:

  1. 查询条件与索引列不匹配 :例如索引是(a, b),但查询只用了b

  2. 使用了函数或表达式WHERE UPPER(name) = 'ABC' 不会使用name上的普通索引

  3. 隐式类型转换 :字符串列用数字查询 WHERE id = '123' 可能导致索引失效

第3步:检查统计信息是否准确

sql

复制代码
-- 查看表的统计信息
SELECT 
    table_name,
    table_rows,
    avg_row_length,
    data_length,
    index_length,
    update_time
FROM information_schema.tables 
WHERE table_schema = '你的数据库名'
AND table_name = '你的表名';

-- 如果怀疑统计信息过时,可以手动收集(在业务低峰期操作)
ANALYZE TABLE 表名 UPDATE STATISTICS;

三、专业方法:查看已执行SQL的实际执行计划

对于已经在运行的SQL,可以查看其实使用的执行计划:

第1步:查找SQL在计划缓存中的信息

sql

复制代码
-- 查找特定SQL(替换your_keyword为你的SQL关键词)
SELECT 
    sql_id,
    plan_id,
    query_sql,
    hits,
    elapsed_time,
    execute_time
FROM GV$OB_PLAN_CACHE_PLAN_STAT 
WHERE query_sql LIKE '%your_keyword%'
LIMIT 10;

第2步:查看实际执行计划

sql

复制代码
-- 使用上一步找到的plan_id(例如123456)
SELECT 
    operator,
    name,
    rows,
    cost,
    property
FROM GV$OB_PLAN_CACHE_PLAN_EXPLAIN 
WHERE plan_id = 123456
ORDER BY line_id;

四、实操示例:完整诊断流程

假设我们发现这条SQL执行很慢:

sql

复制代码
SELECT * FROM orders WHERE customer_id = 100 AND order_date > '2024-01-01';

诊断步骤:

sql

复制代码
-- 1. 查看执行计划
EXPLAIN EXTENDED 
SELECT * FROM orders 
WHERE customer_id = 100 AND order_date > '2024-01-01';

-- 2. 如果看到 TABLE SCAN,检查索引
SHOW INDEX FROM orders;

-- 3. 发现没有 customer_id 上的索引,创建索引
CREATE INDEX idx_customer_id ON orders(customer_id, order_date);

-- 4. 再次查看执行计划,确认是否走索引
EXPLAIN EXTENDED 
SELECT * FROM orders 
WHERE customer_id = 100 AND order_date > '2024-01-01';
-- 现在应该看到 INDEX SCAN 和 idx_customer_id

-- 5. 如果优化器仍然不走索引,可以强制使用(不推荐常规使用)
SELECT /*+ INDEX(orders idx_customer_id) */ * 
FROM orders 
WHERE customer_id = 100 AND order_date > '2024-01-01';

五、快速判断技巧总结

现象 判断 下一步动作
OPERATOR = TABLE SCAN 没走索引 检查是否有合适索引,统计信息是否准确
OPERATOR = INDEX SCAN 走了索引 检查索引是否高效(回表代价等)
OPERATOR = TABLE GET 通过主键访问 通常是最高效的访问方式
预估行数(EST.ROWS)与实际差异大 统计信息可能不准 执行ANALYZE TABLE更新统计信息
有多个可选索引但选错 索引选择问题 使用Hint指定索引或调整索引设计

六、自动化检查脚本

你可以创建一个简单的存储过程来批量检查关键SQL是否走索引:

sql

复制代码
DELIMITER //

CREATE PROCEDURE check_sql_index_usage()
BEGIN
    -- 创建临时表存储结果
    CREATE TEMPORARY TABLE IF NOT EXISTS index_check_result (
        sql_text TEXT,
        uses_index BOOLEAN,
        operator_type VARCHAR(50),
        index_name VARCHAR(100),
        check_time DATETIME
    );
    
    -- 这里可以添加你需要检查的SQL
    INSERT INTO index_check_result
    SELECT 
        'SELECT * FROM users WHERE user_id = 1001' as sql_text,
        CASE WHEN EXISTS (
            SELECT 1 FROM (EXPLAIN FORMAT=JSON SELECT * FROM users WHERE user_id = 1001) t
            WHERE t.EXPLAIN LIKE '%INDEX_SCAN%' OR t.EXPLAIN LIKE '%TABLE_GET%'
        ) THEN TRUE ELSE FALSE END as uses_index,
        '待检查' as operator_type,
        '待检查' as index_name,
        NOW() as check_time;
    
    -- 显示结果
    SELECT * FROM index_check_result;
    
    DROP TEMPORARY TABLE index_check_result;
END //

DELIMITER ;

-- 执行检查
CALL check_sql_index_usage();

通过以上步骤,你可以系统性地诊断OceanBase中SQL的索引使用情况。关键在于先看执行计划,再分析原因,最后针对性优化

相关推荐
qinyia2 小时前
**使用AI助手在智慧运维中快速定位并修复服务异常:以Nginx配置错误导致502错误为例**
linux·运维·服务器·数据库·mysql·nginx·自动化
熊文豪2 小时前
关系数据库替换用金仓——Oracle兼容性深度解析
数据库·oracle·金仓数据库·电科金仓·kes
eWidget2 小时前
面向Oracle生态的国产高兼容数据库解决方案
数据库·oracle·kingbase·数据库平替用金仓·金仓数据库
A懿轩A2 小时前
【MySQL 数据库】MySQL 数据库核心概念详解:库、表、字段、主键与关系型模型一文读懂
数据库·mysql·oracle
盒马coding2 小时前
postgreSQL中调整Checkpoint的重要性
数据库·mysql·postgresql
怣502 小时前
MySQL多表连接完全指南:内连接与外连接(零基础入门版)
数据库·mysql
爱吃山竹的大肚肚2 小时前
文件上传大小超过服务器限制
java·数据库·spring boot·mysql·spring
star12582 小时前
数据分析与科学计算
jvm·数据库·python
2301_822382762 小时前
使用Python进行网络设备自动配置
jvm·数据库·python