MySQL 常用腳本之查看數據庫、表結構、約束、索引等信息

大家好!我是隻談技術不剪髮的 Tony 老師。今天帶來的分享是如何查看 MySQL 數據庫模式以及數據表的結構,包括字段定義、主鍵、外鍵、唯一等約束和索引信息,如何查看錶和索引佔用的磁盤空間等。

數據庫和模式

列出數據庫/模式

在 MySQL 中,數據庫(database)和模式(schema)是相同的概念,可以使用以下查詢列出當前實例中包含的數據庫/模式:

-- 方法一
select schema_name as database_name
from information_schema.schemata
order by schema_name;

-- 方法二
show databases;

-- 方法三
show schemas;

查詢結果中的 information_schema、mysql、performance_schema 以及 sys 屬於系統數據庫/模式。

列出用戶創建的數據庫/模式

將系統數據庫/模式排除之外就是用戶創建的數據庫/模式:

select schema_name as database_name
from information_schema.schemata
where schema_name not in ('information_schema','mysql','performance_schema','sys')
order by schema_name;

查看數據庫的創建語句

使用 SHOW 命令查看數據庫的創建語句:

show create database database_name;
show create schema database_name;

數據表

列出某個數據庫中的表

查看當前數據庫中的表:

-- 方法一
select table_schema as database_name, table_name
from information_schema.tables
where table_type = 'BASE TABLE'
and table_schema = database() 
order by database_name, table_name;

-- 方法二
show tables [LIKE 'pattern' | WHERE expr];

-- 方法三
show table status [LIKE 'pattern' | WHERE expr];

其中,database() 函數返回當前數據庫的名稱。

查看指定數據庫中的表,將查詢條件中的 database_name 替換成需要查詢的數據庫名:

-- 方法一
select table_schema as database_name, table_name
from information_schema.tables
where table_type = 'BASE TABLE'
and table_schema = 'database_name'
order by database_name, table_name;

-- 方法二
show tables {in | from} database_name [LIKE 'pattern' | WHERE expr];
show tables status {in | from} database_name [LIKE 'pattern' | WHERE expr];

列出所有數據庫中的表

select table_schema as database_name, table_name
from information_schema.tables
where table_type = 'BASE TABLE'
order by database_name, table_name;

列出缺少主鍵的表

select tab.table_schema as database_name,
       tab.table_name
from information_schema.tables tab
left join information_schema.table_constraints tco
on tab.table_schema = tco.table_schema and tab.table_name = tco.table_name and tco.constraint_type = 'PRIMARY KEY'
where tco.constraint_type is null
and tab.table_schema not in('mysql', 'information_schema',  'performance_schema', 'sys')
and tab.table_type = 'BASE TABLE'
-- and tab.table_schema = 'sakila'
order by tab.table_schema, tab.table_name;

列出數據庫中的 InnoDB 表

select table_schema as database_name, table_name
from information_schema.tables
where engine = 'InnoDB'
and table_type = 'BASE TABLE'
-- and schema_name not in ('information_schema','mysql','performance_schema','sys')
-- and table_schema = 'database_name'
order by table_schema, table_name;

列出數據庫中的 MyISAM 表

select table_schema as database_name, table_name
from information_schema.tables
where engine = 'MyISAM'
and table_type = 'BASE TABLE'
-- and schema_name not in ('information_schema','mysql','performance_schema','sys')
-- and table_schema = 'database_name'
order by table_schema, table_name;

查看數據表的存儲引擎

select table_schema as database_name, table_name, engine
from information_schema.tables
where table_type = 'BASE TABLE'
-- and schema_name not in ('information_schema','mysql','performance_schema','sys')
-- and table_schema = 'database_name'
order by table_schema, table_name;

查找最近創建的表

使用以下腳本查找最近 30 天之內創建的表:

select table_schema as database_name, table_name, create_time
from information_schema.tables
where table_type = 'BASE TABLE'
and create_time > adddate(current_date, interval - 30 day)
-- and schema_name not in ('information_schema','mysql','performance_schema','sys')
-- and table_schema = 'database_name'
order by create_time desc, table_name;

查找最近修改的表

使用以下腳本查找最近 30 天之內被修改過的表:

select table_schema as database_name, table_name, update_time
from information_schema.tables
where table_type = 'BASE TABLE'
and update_time > (current_timestamp() - interval 30 day)
-- and schema_name not in ('information_schema','mysql','performance_schema','sys')
-- and table_schema = 'database_name'
order by update_time desc, table_name;

以上查詢返回的結果可能不準確,因爲update_time 取決於存儲引擎,具體可以參考官方文檔

查看錶的創建語句

show create table table_name;

字段

列出數據庫中所有表的字段

select tab.table_schema as database_schema,
    tab.table_name as table_name,
    col.ordinal_position as column_id,
    col.column_name as column_name,
    col.data_type as data_type,
    case when col.numeric_precision is not null then col.numeric_precision
         else col.character_maximum_length 
    end as max_length,
    case when col.datetime_precision is not null then col.datetime_precision
         when col.numeric_scale is not null then col.numeric_scale
         else 0 
    end as 'precision'
from information_schema.tables as tab
join information_schema.columns as col
on col.table_schema = tab.table_schema
and col.table_name = tab.table_name
where tab.table_type = 'BASE TABLE'
and tab.table_schema not in ('information_schema','mysql','performance_schema','sys')
-- 查看當前數據庫中的表
-- and tab.table_schema = database() 
-- 查看指定數據庫中的表
-- and tab.table_schema = 'database_name' 
order by tab.table_name, col.ordinal_position;

列出數據庫中指定表的字段

-- 方法一
desc table_name;

-- 方法二
SHOW [EXTENDED] [FULL] {COLUMNS | FIELDS}
    {FROM | IN} table_name
    [{FROM | IN} database_name]
    [LIKE 'pattern' | WHERE expr];

-- 方法二
select ordinal_position as column_id,
    column_name as column_name,
    data_type as data_type,
    case when numeric_precision is not null then numeric_precision
         else character_maximum_length 
    end as max_length,
    case when datetime_precision is not null then datetime_precision
         when numeric_scale is not null then numeric_scale
         else 0 
    end as data_precision,
    is_nullable,
    column_default
from information_schema.columns
where table_name = 'tablename'
and table_schema = 'schema_name'
order by ordinal_position;

列出所有數字類型的字段

select col.table_schema as database_name,
       col.table_name,
       col.ordinal_position as col_id,
       col.column_name,
       col.data_type,
       col.numeric_precision,
       col.numeric_scale
from information_schema.columns col
join information_schema.tables tab 
on tab.table_schema = col.table_schema and tab.table_name = col.table_name and tab.table_type = 'BASE TABLE'
where col.data_type in ('tinyint', 'smallint', 'mediumint', 'int', 'bigint', 
                        'decimal', 'bit', 'float', 'double')
and col.table_schema not in ('information_schema', 'sys', 'performance_schema', 'mysql')
-- and col.table_schema = 'database_name'
-- and col.table_name = 'table_name'
order by col.table_schema, col.table_name, col.ordinal_position;

列出所有字符類型的字段

select col.table_schema as database_name,
       col.table_name,
       col.ordinal_position as col_id,
       col.column_name,
       col.data_type,
       col.numeric_precision,
       col.numeric_scale
from information_schema.columns col
join information_schema.tables tab 
on tab.table_schema = col.table_schema and tab.table_name = col.table_name and tab.table_type = 'BASE TABLE'
where col.data_type in ('char', 'varchar', 'binary', 'varbinary', 
                        'blob', 'tinyblob', 'mediumblob', 'longblob',
                        'text', 'tinytext', 'mediumtext', 'longtext'
                        'enum', 'set')
and col.table_schema not in ('information_schema', 'sys', 'performance_schema', 'mysql')
-- and col.table_schema = 'database_name'
-- and col.table_name = 'table_name'
order by col.table_schema, col.table_name, col.ordinal_position;

列出所有日期時間類型的字段

select col.table_schema as database_name,
       col.table_name,
       col.ordinal_position as col_id,
       col.column_name,
       col.data_type,
       col.numeric_precision,
       col.numeric_scale
from information_schema.columns col
join information_schema.tables tab 
on tab.table_schema = col.table_schema and tab.table_name = col.table_name and tab.table_type = 'BASE TABLE'
where col.data_type in ('date', 'time', 'datetime', 'year', 'timestamp')
and col.table_schema not in ('information_schema', 'sys', 'performance_schema', 'mysql')
-- and col.table_schema = 'database_name'
-- and col.table_name = 'table_name'
order by col.table_schema, col.table_name, col.ordinal_position;

列出字段的詳細信息

以下查詢用於列出字段的詳細信息,包括是否主鍵、外鍵、唯一、默認值、是否可空以及計算列的表達式等:

select col.table_schema as database_name,
       col.table_name,
       col.column_name,
       col.data_type,
       case when col.data_type in ('datetime', 'timestamp', 'time') then col.datetime_precision
            else col.numeric_precision 
       end as 'precision',
       col.numeric_scale,
       col.character_maximum_length as char_length,
       col.column_default,
       col.generation_expression,
       case when (group_concat(constraint_type separator ', ')) like '%PRIMARY KEY%' then 'YES' 
            else 'NO' 
       end as PK,
       case when (group_concat(constraint_type separator ', ')) like '%UNIQUE%' then 'YES' 
            else 'NO' 
       end as UQ,
       case when (group_concat(constraint_type separator ', ')) like '%FOREIGN KEY%' then 'YES' 
            else 'NO' 
       end as FK,
       col.is_nullable
from information_schema.columns col
join information_schema.tables tab
on col.table_schema = tab.table_schema and col.table_name = tab.table_name and tab.table_type = 'BASE TABLE'
left join information_schema.key_column_usage kcu
on col.table_schema = kcu.table_schema and col.table_name = kcu.table_name and col.column_name = kcu.column_name
left join information_schema.table_constraints tco
on kcu.constraint_schema = tco.constraint_schema and kcu.constraint_name = tco.constraint_name and kcu.table_name = tco.table_name
where tab.table_schema not in ('information_schema','mysql','performance_schema','sys')
-- 查看當前數據庫中的表
-- and tab.table_schema = database() 
-- 查看指定數據庫中的表
-- and tab.table_schema = 'database_name' 
group by 1,2,3,4,5,6,7,8,9,13
order by col.table_schema, col.table_name, col.column_name;

列出計算列及其表達式

select table_schema as database_name,
       table_name,
       column_name,
       data_type,
       generation_expression
from information_schema.columns 
where length(generation_expression) > 0
and table_schema not in  ('information_schema','mysql','performance_schema','sys')
-- 查看當前數據庫中的表
-- and table_schema = database() 
-- 查看指定數據庫中的表
-- and table_schema = 'database_name' 
-- 查看指定表
-- and table_name = 'tablename' 
order by table_schema, table_name, column_name;

主鍵、外鍵、唯一等約束

列出指定數據庫中的主鍵約束

select tab.table_schema as database_schema,
    sta.index_name as pk_name,
    sta.seq_in_index as column_id,
    sta.column_name,
    tab.table_name
from information_schema.tables as tab
join information_schema.statistics as sta
on sta.table_schema = tab.table_schema and sta.table_name = tab.table_name and sta.index_name = 'primary'
where tab.table_schema = 'database_name'
and tab.table_type = 'BASE TABLE'
order by tab.table_name, column_id;

列出指定數據庫中的外鍵約束

select concat(col.table_schema, '.', col.table_name) as 'foreign_table',
       col.column_name as column_name,
       '->' as rel,
       concat(kcu.referenced_table_schema, '.', kcu.referenced_table_name) as primary_table,
       kcu.referenced_column_name as pk_column_name,
       kcu.constraint_name as fk_constraint_name
from information_schema.columns col
join information_schema.tables tab
on col.table_schema = tab.table_schema and col.table_name = tab.table_name
left join information_schema.key_column_usage kcu
on col.table_schema = kcu.table_schema and col.table_name = kcu.table_name and col.column_name = kcu.column_name
where col.table_schema not in('information_schema','sys', 'mysql', 'performance_schema')
and tab.table_type = 'BASE TABLE'
and kcu.referenced_table_schema is not null
and tab.table_schema = 'hrdb'
order by col.table_schema, col.table_name, col.ordinal_position;

列出指定數據庫中的唯一約束

select stat.table_schema as database_name,
       stat.table_name,
       stat.index_name,
       group_concat(stat.column_name order by stat.seq_in_index separator ', ') as columns,
       tco.constraint_type
from information_schema.statistics stat
join information_schema.table_constraints tco
on stat.table_schema = tco.table_schema and stat.table_name = tco.table_name and stat.index_name = tco.constraint_name
where stat.non_unique = 0
and stat.table_schema not in ('information_schema', 'sys', 'performance_schema', 'mysql')
and stat.table_schema = 'database_name'
group by stat.table_schema, stat.table_name, stat.index_name, tco.constraint_type
order by stat.table_schema, stat.table_name;

列出指定數據庫中的字段默認值

select table_schema as database_name,
       table_name,
       column_name,
       column_default
from information_schema.columns
where column_default is not null
and table_schema not in ('information_schema', 'sys', 'performance_schema','mysql')
and table_schema = 'database_name'
order by table_schema, table_name, ordinal_position;

索引

列出指定數據庫中的索引

select table_schema as database_name,
       table_name,
       index_name,
       group_concat(column_name order by seq_in_index) as columns,
       index_type,
       case non_unique
            when 1 then 'Not Unique'
            else 'Unique'
       end as is_unique
from information_schema.statistics
where table_schema not in ('information_schema', 'mysql', 'performance_schema', 'sys')
and table_schema = 'database_name'
group by table_schema, table_name, index_name, index_type, non_unique
order by table_schema, table_name;

列出指定表中的索引

-- 方法一
SHOW [EXTENDED] {INDEX | INDEXES | KEYS}
    {FROM | IN} table_name
    [{FROM | IN} database_name]
    [WHERE expr];

-- 方法二
select table_schema as database_name,
       table_name,
       index_name,
       group_concat(column_name order by seq_in_index) as columns,
       index_type,
       case non_unique
            when 1 then 'Not Unique'
            else 'Unique'
       end as is_unique
from information_schema.statistics
where table_schema not in ('information_schema', 'mysql', 'performance_schema', 'sys')
and table_schema = 'database_name'
and table_name = 'table_name'
group by table_schema, table_name, index_name, index_type, non_unique
order by table_schema, table_name;

數據行及大小

查詢表中的行數

對於不同的存儲引擎使用不同的查詢方法:

-- MyISAM 存儲引擎表
select table_schema, table_name, table_rows
from information_schema.tables
where table_type = 'BASE TABLE'
and engine = 'MyISAM'
and table_schema not in ('information_schema', 'mysql', 'performance_schema', 'sys')
-- and table_schema = 'database_name'
-- and table_name = 'table_name'
order by table_schema, table_name;

-- InnoDB 存儲引擎表
select count(*) from table_name;

查看錶分配和使用的空間

select table_schema as database_name,
    table_name,
    round(sum((data_length + index_length)) / power(1024, 2), 2) as used_mb,
    round(sum((data_length + index_length + data_free)) /power(1024, 2), 2) as allocated_mb,
    round(sum(data_free) /power(1024, 2), 2) as free_mb
from information_schema.tables
where table_type = 'BASE TABLE'
and table_schema not in ('information_schema', 'mysql', 'performance_schema', 'sys')
-- and table_schema = 'database_name'
-- and table_name = 'table_name'
group by table_schema, table_name
order by used_mb desc;

查看錶中數據和索引的使用空間

select table_schema as database_name,
    table_name,
    engine,
    round(1.0*data_length/1024/1024, 2) as data_size_mb,
    round(index_length/1024/1024, 2) as index_size_mb,
    round((data_length + index_length)/1024/1024, 2) as total_size_mb
from information_schema.tables
where table_type = 'BASE TABLE'
and table_schema not in ('information_schema', 'mysql', 'performance_schema', 'sys')
-- and table_schema = 'database_name'
-- and table_name = 'table_name'
order by total_size_mb desc;

對於 InnoDB 表,data_length 字段表示聚集索引的大小(包含了所有的數據)。InnoDB 表的 index_length 和 data_length 返回的是近似值。

查看 InnoDB 輔助索引佔用的空間

select database_name,
       table_name,
       index_name,
       (1.0*stat_value*@@innodb_page_size/1024/1024) as index_size_mb
from mysql.innodb_index_stats
where stat_name = 'size'
and index_name not in ('PRIMARY', 'GEN_CLUST_INDEX')
-- and database_name = 'database_name'
-- and table_name = 'table_name'
order by index_size_mb desc;

查看 LOB 大對象佔用的空間

select tab.table_schema as database_name, tab.table_name,
    round(sum(data_length + index_length) / power(1024, 2), 2) as used_mb,
    round(sum(data_length + index_length + data_free) / power(1024, 2), 2) as allocated_mb
from information_schema.tables as tab
join information_schema.columns as col 
on col.table_schema = tab.table_schema and col.table_name = tab.table_name
where tab.table_type = 'BASE TABLE'
and tab.table_schema not in ('information_schema', 'mysql', 'performance_schema', 'sys')
and col.data_type in ('blob', 'mediumblob', 'longblob', 'text', 'mediumtext', 'longtext')
-- and tab.table_schema = 'database_name'
-- and tab.table_name = 'table_name'
group by 1,2
order by 2;

數據庫比較

比較兩個數據庫中的表和字段信息

以下查詢比較兩個數據庫中的所有表,返回任意數據庫中越少的字段:

set @database_1 = 'database_name_1'; -- provide first database name here
set @database_2 = 'database_name_2'; -- provide second database name here
select * 
from (
        select COALESCE(c1.table_name, c2.table_name) as table_name,
               COALESCE(c1.column_name, c2.column_name) as table_column,
               c1.column_name as database1,
               c2.column_name as database2
        from
            (select table_name,
                    column_name
             from information_schema.columns c
             where c.table_schema = @database_1) c1
        right join
                 (select table_name,
                         column_name
                  from information_schema.columns c
                  where c.table_schema = @database_2) c2
        on c1.table_name = c2.table_name and c1.column_name = c2.column_name
    union
        select COALESCE(c1.table_name, c2.table_name) as table_name,
               COALESCE(c1.column_name, c2.column_name) as table_column,
               c1.column_name as schema1,
               c2.column_name as schema2
        from
            (select table_name,
                    column_name
             from information_schema.columns c
             where c.table_schema = @database_1) c1
        left join
                 (select table_name,
                         column_name
                  from information_schema.columns c
                  where c.table_schema = @database_2) c2
        on c1.table_name = c2.table_name and c1.column_name = c2.column_name
) tmp
where database1 is null
      or database2 is null
order by table_name,
         table_column;
set @database_1 = null;
set @database_2 = null;

寫作不易,如果你點擊了收藏⭐,請不要忘了關注❤️、評論📝、點贊👍!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章