检查SQL语句中的表是否已创建列索引

存储过程dbms_imci.check_columnar_index()可以解析输入的SQL语句,并得到SQL语句中使用的所有列,并检查这些列是否被列索引覆盖。

  • 如果SQL语句中使用了未被列索引覆盖的列,调用该存储过程后会返回这些列所在的库名、表名以及列名。

  • 如果SQL语句中使用的所有列都已经被列索引覆盖,调用该存储过程会返回空的结果集。

前提条件

  • PolarDB集群版本需满足以下条件之一:

    • PolarDB MySQL版8.0.1版本且修订版本为8.0.1.1.30及以上。

    • PolarDB MySQL版8.0.2版本且修订版本为8.0.2.2.12及以上。

  • 您需要具有所操作的表的读(SELECT)权限。

语法

dbms_imci.check_columnar_index('<query_string>');

参数说明

参数

说明

query_string

需要解析的SQL语句。

说明
  • 该SQL语句必须是符合规范的SELECT语句,不支持INSERTUPDATEDELETE等其他DML语句。如果SELECT语句不符合规范(例如引用了不存在的列),会返回相对应的错误信息。

  • query_string必须是字符串,不能使用变量值或查询结果作为输入。

注意事项

  • 存储过程名称区分大小写。

  • 使用该存储过程解析SQL语句时,如果SQL语句中的表名前添加了库名,则使用SQL语句中的库名。如果SQL语句中的表名前没有添加库名,则必须使用use db_name命令切换至SQL语句中的表所在的库后,再执行该存储过程。

  • SQL语句没有特殊的长度限制,但客户端向数据库发送的SQL语句长度受限于max_allowed_packet等参数,以及解析SQL语句时使用的thread_stack参数。

  • 如果列存索引不支持SQL语句中使用的列的类型,调用该存储过程时会返回错误信息。

  • SELECT语句可以为Prepared Statement的参数化形式,但不能添加PREPARE ... FROM关键词。

  • 如果SQL语句中使用了'"等需要转义的字符,则需要按照MySQL的语法规则进行转义。示例如下:

    • 将SQL语句中的' 换成 ''

      call dbms_imci.check_columnar_index('select t1.a from t1 where t1.b = ''some_string''');
    • 将SQL语句中的"换成 ""

      call dbms_imci.check_columnar_index("select t1.a from t1 where t1.b = ""some_string""");

    更多转义规则请参见MySQL官网

示例

t1t2t3表为例,调用存储过程检查SQL语句中是否存在未被列存索引覆盖的列。

  1. 执行如下命令,切换至test库。

    use test;
  2. 执行如下命令,创建t1t2t3表,其中t3表的所有列都被列索引覆盖。

    create table t1 (a int, b int) engine = innodb;
    create table t2 (a int, b int) engine = innodb;
    create table t3 (a int, b int) engine = innodb comment 'columnar=1';
  3. 调用存储过程,检查SQL语句中是否有未被列索引覆盖的列。

    • SQL语句中的列为t1t2表中的列。

      call dbms_imci.check_columnar_index('select count(t1.a) from t1 inner join t2 on t1.a = t2.a group by t1.b');

      执行结果如下:

      +--------------+------------+-------------+
      | TABLE_SCHEMA | TABLE_NAME | COLUMN_NAME |
      +--------------+------------+-------------+
      | test         | t1         | a           |
      | test         | t1         | b           |
      | test         | t2         | a           |
      +--------------+------------+-------------+
      3 rows in set (0.01 sec)

      SQL语句中使用了t1.at1.b以及t2.a三列,且这三列没有被列索引覆盖。因此,调用该存储过程时,返回这三列对应的库名、表名以及列名。

    • SQL语句中的列为表t3中的列。

      call dbms_imci.check_columnar_index('select a, b from t3');

      执行结果如下:

      Empty set (0.00 sec)

      t3中的所有列都被列索引覆盖。因此,调用该存储过程时,返回空结果集。