从简单到专业在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的索引使用情况。关键在于先看执行计划,再分析原因,最后针对性优化

相关推荐
做个文艺程序员4 小时前
MySQL 主从延迟根因诊断法
数据库·mysql
计算机安禾4 小时前
【数据结构与算法】第33篇:交换排序(二):快速排序
c语言·开发语言·数据结构·数据库·算法·矩阵·排序算法
l1t4 小时前
测试clickhouse 26.3的新功能
数据库·clickhouse
Mike117.5 小时前
GBase 8a 批处理任务里的事务提交粒度和回滚边界
数据库
小江的记录本5 小时前
【JEECG Boot】 《JEECG Boot 数据字典使用教程》(完整版)
java·前端·数据库·spring boot·后端·spring·mybatis
yjb.gz5 小时前
Oracle物化视图概述
数据库·oracle
fundoit5 小时前
MySQL Workbench中的权限设置不生效
数据库·mysql
ZzzZZzzzZZZzzzz…5 小时前
MySQL备份还原方法2----LVM
linux·运维·数据库·mysql·备份还原
i220818 Faiz Ul5 小时前
教育资源共享平台|基于springboot + vue教育资源共享平台系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·教育资源共享平台
玛卡巴卡ldf5 小时前
【Springboot7】ApachePOI文件导入导出
java·spring boot·sql