如何检查独立于使用的 SQL 数据库的列上是否存在 INDEX

Bjö*_*obs 5 mysql index information-schema

无论使用的实际 SQL 数据库系统如何,是否有统一的方法来检查给定列的 INDEX 是否存在?

例如,对于 MySQL,可以使用SHOW CREATE TABLE mytable. 如果列mycolumn有一个索引,结果会是这样的:KEY 'Index_1' ('mycolumn')

这个指标KEY是所有SQL数据库系统统一的吗?

有没有更好的方法来检查索引?

Phi*_*lᵀᴹ 7

恐怕不是。

ANSI SQL 标准在模式 (" INFORMATION_SCHEMA") 中定义了一些数据字典视图,可用于查找特定类型的对象(表、视图、表列),但它不包含任何有关索引的内容。

大多数 RDBMS 都有自己的内部数据字典视图来公开这些信息(例如,sysindexes在 SQL Server 和 Sybase 中,DBA_INDEXES在 Oracle 中)。


Rol*_*DBA 5

当涉及到 MySQL 时,您需要搜索INFORMATION_SCHEMA 数据库

下表将允许您在所有索引中查找一列。

表格说明

INFORMATION_SCHEMA.KEY_COLUMN_USAGE

mysql> show create table information_schema.key_column_usage\G
*************************** 1. row ***************************
       Table: KEY_COLUMN_USAGE
Create Table: CREATE TEMPORARY TABLE `KEY_COLUMN_USAGE` (
  `CONSTRAINT_CATALOG` varchar(512) NOT NULL DEFAULT '',
  `CONSTRAINT_SCHEMA` varchar(64) NOT NULL DEFAULT '',
  `CONSTRAINT_NAME` varchar(64) NOT NULL DEFAULT '',
  `TABLE_CATALOG` varchar(512) NOT NULL DEFAULT '',
  `TABLE_SCHEMA` varchar(64) NOT NULL DEFAULT '',
  `TABLE_NAME` varchar(64) NOT NULL DEFAULT '',
  `COLUMN_NAME` varchar(64) NOT NULL DEFAULT '',
  `ORDINAL_POSITION` bigint(10) NOT NULL DEFAULT '0',
  `POSITION_IN_UNIQUE_CONSTRAINT` bigint(10) DEFAULT NULL,
  `REFERENCED_TABLE_SCHEMA` varchar(64) DEFAULT NULL,
  `REFERENCED_TABLE_NAME` varchar(64) DEFAULT NULL,
  `REFERENCED_COLUMN_NAME` varchar(64) DEFAULT NULL
) ENGINE=MEMORY DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

INFORMATION_SCHEMA.STATISTICS

mysql> show create table information_schema.statistics\G
*************************** 1. row ***************************
       Table: STATISTICS
Create Table: CREATE TEMPORARY TABLE `STATISTICS` (
  `TABLE_CATALOG` varchar(512) NOT NULL DEFAULT '',
  `TABLE_SCHEMA` varchar(64) NOT NULL DEFAULT '',
  `TABLE_NAME` varchar(64) NOT NULL DEFAULT '',
  `NON_UNIQUE` bigint(1) NOT NULL DEFAULT '0',
  `INDEX_SCHEMA` varchar(64) NOT NULL DEFAULT '',
  `INDEX_NAME` varchar(64) NOT NULL DEFAULT '',
  `SEQ_IN_INDEX` bigint(2) NOT NULL DEFAULT '0',
  `COLUMN_NAME` varchar(64) NOT NULL DEFAULT '',
  `COLLATION` varchar(1) DEFAULT NULL,
  `CARDINALITY` bigint(21) DEFAULT NULL,
  `SUB_PART` bigint(3) DEFAULT NULL,
  `PACKED` varchar(10) DEFAULT NULL,
  `NULLABLE` varchar(3) NOT NULL DEFAULT '',
  `INDEX_TYPE` varchar(16) NOT NULL DEFAULT '',
  `COMMENT` varchar(16) DEFAULT NULL,
  `INDEX_COMMENT` varchar(1024) NOT NULL DEFAULT ''
) ENGINE=MEMORY DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

例如,您可以搜索具有Column_Name_I_Want如下列的索引:

示例#1

SELECT table_schema DB,table_name TBL,
    constraint_name NDX,
    seq_in_index NDX_POS,position_in_unique_constraint CONST_POS
FROM information_schema.key_column_usage WHERE column_name = 'Column_Name_I_Want'
AND table_schema NOT IN ('information_schema','mysql','performance_schema');
Run Code Online (Sandbox Code Playgroud)

示例#2

SELECT
    table_schema DB,table_name TBL,
    index_name NDX,seq_in_index NDXPOS
FROM information_schema.statistics WHERE column_name = 'Column_Name_I_Want'
AND table_schema NOT IN ('information_schema','mysql','performance_schema');
Run Code Online (Sandbox Code Playgroud)

警告

请注意,这些类型的查询会很慢,因为 MySQL 的 INFORMATION_SCHEMA

  • 是没有索引的 MEMORY 表
  • 访问 InnoDB 很慢
    • 有很多桌子
    • 打开文件句柄只是为了读取元数据
    • 使用 InnoDB 表访问其元数据
  • 访问具有数百个分区的分区 MyISAM 表很慢
  • 快速访问未分区的 MyISAM 表