The Information Schema is a built-in database in MySQL and MariaDB that provides access to metadata about all other databases, tables, columns, privileges, and database objects on the server. Think of it as a "database about databases" - a comprehensive catalog that stores information about the structure and properties of your database system.
What is Information Schema?
The Information Schema is a standardized way to access metadata across different database management systems. In MySQL/MariaDB, it appears as a read-only database named information_schema that contains views (virtual tables) providing detailed information about:
- Databases and their properties
- Tables and their structure
- Columns and their data types
- Indexes and constraints
- User privileges and permissions
- Storage engines and their capabilities
- Server statistics and status information
Key Characteristics
Read-Only Nature: You cannot modify data in Information Schema directly - it's automatically maintained by the database server.
Virtual Tables: Information Schema consists of views, not physical tables, so the data is generated dynamically when queried.
Standard Compliance: Based on the SQL standard (ANSI SQL), making knowledge transferable to other database systems.
Real-Time Data: Information is always current, reflecting the immediate state of your database system.
Accessing Information Schema
Basic Access Methods
1. Through phpMyAdmin:
- Log into phpMyAdmin
- Look for
information_schema in the left database list
- Click to expand and explore the available tables/views
2. Through Command Line:
-- Connect to MySQL and use information_schema
mysql -u username -p
USE information_schema;
SHOW TABLES;
3. Direct Queries:
-- Query without changing database context
SELECT * FROM information_schema.SCHEMATA;
Core Information Schema Tables
SCHEMATA - Database Information
Lists all databases on the server:
-- View all databases
SELECT
SCHEMA_NAME as 'Database Name',
DEFAULT_CHARACTER_SET_NAME as 'Character Set',
DEFAULT_COLLATION_NAME as 'Collation'
FROM information_schema.SCHEMATA;
-- Find databases you have access to
SELECT SCHEMA_NAME
FROM information_schema.SCHEMATA
WHERE SCHEMA_NAME NOT IN ('information_schema', 'mysql', 'performance_schema', 'sys');
TABLES - Table Information
Provides detailed information about all tables:
-- Get table information for a specific database
SELECT
TABLE_NAME as 'Table Name',
ENGINE as 'Storage Engine',
TABLE_ROWS as 'Estimated Rows',
DATA_LENGTH as 'Data Size (bytes)',
INDEX_LENGTH as 'Index Size (bytes)',
CREATE_TIME as 'Created',
UPDATE_TIME as 'Last Updated'
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'your_database_name'
ORDER BY DATA_LENGTH DESC;
-- Find all MyISAM tables
SELECT TABLE_SCHEMA, TABLE_NAME
FROM information_schema.TABLES
WHERE ENGINE = 'MyISAM';
-- Calculate total database size
SELECT
TABLE_SCHEMA as 'Database',
ROUND(SUM(DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024, 2) as 'Size (MB)'
FROM information_schema.TABLES
GROUP BY TABLE_SCHEMA;
COLUMNS - Column Information
Detailed information about table columns:
-- Get column details for a specific table
SELECT
COLUMN_NAME as 'Column',
DATA_TYPE as 'Type',
IS_NULLABLE as 'Nullable',
COLUMN_DEFAULT as 'Default',
COLUMN_KEY as 'Key',
EXTRA as 'Extra Info'
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'your_database'
AND TABLE_NAME = 'your_table'
ORDER BY ORDINAL_POSITION;
-- Find all AUTO_INCREMENT columns
SELECT
TABLE_SCHEMA,
TABLE_NAME,
COLUMN_NAME,
AUTO_INCREMENT
FROM information_schema.COLUMNS
WHERE EXTRA = 'auto_increment';
-- Find columns with specific data type
SELECT
TABLE_SCHEMA,
TABLE_NAME,
COLUMN_NAME
FROM information_schema.COLUMNS
WHERE DATA_TYPE = 'text';
STATISTICS - Index Information
Information about table indexes:
-- View indexes for a specific table
SELECT
INDEX_NAME as 'Index Name',
COLUMN_NAME as 'Column',
NON_UNIQUE as 'Non-Unique',
SEQ_IN_INDEX as 'Position',
CARDINALITY as 'Cardinality'
FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = 'your_database'
AND TABLE_NAME = 'your_table'
ORDER BY INDEX_NAME, SEQ_IN_INDEX;
-- Find tables without primary keys
SELECT
TABLE_SCHEMA,
TABLE_NAME
FROM information_schema.TABLES
WHERE TABLE_SCHEMA NOT IN ('information_schema', 'mysql', 'performance_schema', 'sys')
AND TABLE_NAME NOT IN (
SELECT DISTINCT TABLE_NAME
FROM information_schema.STATISTICS
WHERE INDEX_NAME = 'PRIMARY'
AND TABLE_SCHEMA = TABLES.TABLE_SCHEMA
);
Practical Use Cases and Examples
1. Database Administration Tasks
Monitoring Database Growth:
-- Track database size over time
SELECT
TABLE_SCHEMA as 'Database',
COUNT(*) as 'Tables',
ROUND(SUM(DATA_LENGTH) / 1024 / 1024, 2) as 'Data (MB)',
ROUND(SUM(INDEX_LENGTH) / 1024 / 1024, 2) as 'Index (MB)',
ROUND(SUM(DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024, 2) as 'Total (MB)'
FROM information_schema.TABLES
WHERE TABLE_SCHEMA NOT IN ('information_schema', 'mysql', 'performance_schema', 'sys')
GROUP BY TABLE_SCHEMA
ORDER BY SUM(DATA_LENGTH + INDEX_LENGTH) DESC;
Finding Unused Tables:
-- Tables that haven't been updated recently (MariaDB/MySQL 5.7+)
SELECT
TABLE_SCHEMA,
TABLE_NAME,
UPDATE_TIME,
TABLE_ROWS
FROM information_schema.TABLES
WHERE UPDATE_TIME IS NOT NULL
AND UPDATE_TIME < DATE_SUB(NOW(), INTERVAL 6 MONTH)
AND TABLE_SCHEMA NOT IN ('information_schema', 'mysql', 'performance_schema', 'sys');
2. Security and Permissions Auditing
User Privileges Overview:
-- View user privileges (requires appropriate permissions)
SELECT
GRANTEE as 'User',
TABLE_SCHEMA as 'Database',
PRIVILEGE_TYPE as 'Privilege',
IS_GRANTABLE as 'Can Grant'
FROM information_schema.SCHEMA_PRIVILEGES
ORDER BY GRANTEE, TABLE_SCHEMA;
-- Check column-level privileges
SELECT
GRANTEE,
TABLE_SCHEMA,
TABLE_NAME,
COLUMN_NAME,
PRIVILEGE_TYPE
FROM information_schema.COLUMN_PRIVILEGES;
3. Schema Analysis and Documentation
Generate Table Documentation:
-- Create a comprehensive table report
SELECT
t.TABLE_NAME as 'Table',
t.ENGINE as 'Engine',
t.TABLE_ROWS as 'Rows',
ROUND((t.DATA_LENGTH + t.INDEX_LENGTH) / 1024 / 1024, 2) as 'Size (MB)',
t.TABLE_COMMENT as 'Comment',
GROUP_CONCAT(
CONCAT(c.COLUMN_NAME, ' (', c.DATA_TYPE,
CASE WHEN c.CHARACTER_MAXIMUM_LENGTH IS NOT NULL
THEN CONCAT('(', c.CHARACTER_MAXIMUM_LENGTH, ')')
ELSE '' END, ')')
ORDER BY c.ORDINAL_POSITION
SEPARATOR ', '
) as 'Columns'
FROM information_schema.TABLES t
LEFT JOIN information_schema.COLUMNS c ON t.TABLE_NAME = c.TABLE_NAME
AND t.TABLE_SCHEMA = c.TABLE_SCHEMA
WHERE t.TABLE_SCHEMA = 'your_database_name'
GROUP BY t.TABLE_NAME
ORDER BY t.TABLE_NAME;
Foreign Key Relationships:
-- Find foreign key relationships
SELECT
kcu.TABLE_SCHEMA as 'Database',
kcu.TABLE_NAME as 'Table',
kcu.COLUMN_NAME as 'Column',
kcu.REFERENCED_TABLE_NAME as 'References Table',
kcu.REFERENCED_COLUMN_NAME as 'References Column',
rc.UPDATE_RULE as 'On Update',
rc.DELETE_RULE as 'On Delete'
FROM information_schema.KEY_COLUMN_USAGE kcu
JOIN information_schema.REFERENTIAL_CONSTRAINTS rc
ON kcu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME
AND kcu.TABLE_SCHEMA = rc.CONSTRAINT_SCHEMA
WHERE kcu.REFERENCED_TABLE_NAME IS NOT NULL
ORDER BY kcu.TABLE_SCHEMA, kcu.TABLE_NAME;
4. Performance Analysis
Identify Large Tables:
-- Find tables consuming the most space
SELECT
TABLE_SCHEMA as 'Database',
TABLE_NAME as 'Table',
ENGINE as 'Engine',
TABLE_ROWS as 'Rows',
ROUND(DATA_LENGTH / 1024 / 1024, 2) as 'Data (MB)',
ROUND(INDEX_LENGTH / 1024 / 1024, 2) as 'Index (MB)',
ROUND((DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024, 2) as 'Total (MB)',
ROUND(INDEX_LENGTH / DATA_LENGTH * 100, 2) as 'Index Ratio (%)'
FROM information_schema.TABLES
WHERE TABLE_SCHEMA NOT IN ('information_schema', 'mysql', 'performance_schema', 'sys')
AND DATA_LENGTH > 0
ORDER BY (DATA_LENGTH + INDEX_LENGTH) DESC
LIMIT 20;
Index Analysis:
-- Find duplicate indexes
SELECT
TABLE_SCHEMA,
TABLE_NAME,
GROUP_CONCAT(INDEX_NAME) as 'Duplicate Indexes',
GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX) as 'Columns'
FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA NOT IN ('information_schema', 'mysql', 'performance_schema', 'sys')
GROUP BY TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX)
HAVING COUNT(*) > 1;
5. Data Type Analysis
Find Data Type Inconsistencies:
-- Find columns with same name but different data types
SELECT
COLUMN_NAME,
GROUP_CONCAT(DISTINCT CONCAT(DATA_TYPE,
CASE WHEN CHARACTER_MAXIMUM_LENGTH IS NOT NULL
THEN CONCAT('(', CHARACTER_MAXIMUM_LENGTH, ')')
ELSE '' END)
SEPARATOR ', ') as 'Different Types',
COUNT(DISTINCT DATA_TYPE) as 'Type Count'
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA NOT IN ('information_schema', 'mysql', 'performance_schema', 'sys')
GROUP BY COLUMN_NAME
HAVING COUNT(DISTINCT DATA_TYPE) > 1
ORDER BY COLUMN_NAME;
Character Set and Collation Analysis:
-- Check character set consistency
SELECT
TABLE_SCHEMA,
CHARACTER_SET_NAME,
COLLATION_NAME,
COUNT(*) as 'Column Count'
FROM information_schema.COLUMNS
WHERE CHARACTER_SET_NAME IS NOT NULL
GROUP BY TABLE_SCHEMA, CHARACTER_SET_NAME, COLLATION_NAME
ORDER BY TABLE_SCHEMA, CHARACTER_SET_NAME;
Advanced Information Schema Queries
1. Routine and Function Information
-- View stored procedures and functions
SELECT
ROUTINE_SCHEMA as 'Database',
ROUTINE_NAME as 'Routine Name',
ROUTINE_TYPE as 'Type',
DATA_TYPE as 'Returns',
CREATED as 'Created Date',
LAST_ALTERED as 'Modified Date',
ROUTINE_COMMENT as 'Comment'
FROM information_schema.ROUTINES
WHERE ROUTINE_SCHEMA NOT IN ('information_schema', 'mysql', 'performance_schema', 'sys')
ORDER BY ROUTINE_SCHEMA, ROUTINE_TYPE, ROUTINE_NAME;
-- Get routine parameters
SELECT
SPECIFIC_SCHEMA as 'Database',
SPECIFIC_NAME as 'Routine',
PARAMETER_MODE as 'Mode',
PARAMETER_NAME as 'Parameter',
DATA_TYPE as 'Data Type'
FROM information_schema.PARAMETERS
WHERE SPECIFIC_SCHEMA = 'your_database_name'
ORDER BY SPECIFIC_NAME, ORDINAL_POSITION;
2. Trigger Information
-- View all triggers
SELECT
TRIGGER_SCHEMA as 'Database',
EVENT_OBJECT_TABLE as 'Table',
TRIGGER_NAME as 'Trigger Name',
EVENT_MANIPULATION as 'Event',
ACTION_TIMING as 'Timing',
CREATED as 'Created'
FROM information_schema.TRIGGERS
WHERE TRIGGER_SCHEMA = 'your_database_name'
ORDER BY EVENT_OBJECT_TABLE, ACTION_TIMING, EVENT_MANIPULATION;
3. View Information
-- List all views
SELECT
TABLE_SCHEMA as 'Database',
TABLE_NAME as 'View Name',
IS_UPDATABLE as 'Updatable',
CHECK_OPTION as 'Check Option'
FROM information_schema.VIEWS
WHERE TABLE_SCHEMA = 'your_database_name'
ORDER BY TABLE_NAME;
Creating Custom Monitoring Queries
Database Health Dashboard
-- Comprehensive database overview
SELECT
'Database Count' as 'Metric',
COUNT(*) as 'Value'
FROM information_schema.SCHEMATA
WHERE SCHEMA_NAME NOT IN ('information_schema', 'mysql', 'performance_schema', 'sys')
UNION ALL
SELECT
'Total Tables',
COUNT(*)
FROM information_schema.TABLES
WHERE TABLE_SCHEMA NOT IN ('information_schema', 'mysql', 'performance_schema', 'sys')
UNION ALL
SELECT
'Total Columns',
COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA NOT IN ('information_schema', 'mysql', 'performance_schema', 'sys')
UNION ALL
SELECT
'Total Indexes',
COUNT(DISTINCT CONCAT(TABLE_SCHEMA, '.', TABLE_NAME, '.', INDEX_NAME))
FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA NOT IN ('information_schema', 'mysql', 'performance_schema', 'sys')
UNION ALL
SELECT
'Total Size (MB)',
ROUND(SUM(DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024, 2)
FROM information_schema.TABLES
WHERE TABLE_SCHEMA NOT IN ('information_schema', 'mysql', 'performance_schema', 'sys');
Schema Comparison Tool
-- Compare table structures between databases
SELECT
'Only in DB1' as 'Status',
TABLE_NAME
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'database1'
AND TABLE_NAME NOT IN (
SELECT TABLE_NAME
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'database2'
)
UNION ALL
SELECT
'Only in DB2',
TABLE_NAME
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'database2'
AND TABLE_NAME NOT IN (
SELECT TABLE_NAME
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'database1'
)
ORDER BY Status, TABLE_NAME;
Performance Considerations
Efficient Information Schema Queries
Best Practices:
- Always filter by schema name:
-- Good: Filtered query
SELECT * FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'specific_database';
-- Avoid: Unfiltered queries on large systems
SELECT * FROM information_schema.TABLES;
- Use appropriate LIMIT clauses:
-- For exploratory queries
SELECT * FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'your_db'
LIMIT 100;
- Index-friendly WHERE conditions:
-- Use indexed columns in WHERE clauses
SELECT * FROM information_schema.KEY_COLUMN_USAGE
WHERE CONSTRAINT_SCHEMA = 'your_db'
AND CONSTRAINT_NAME = 'PRIMARY';
Query Optimization Tips
Avoid expensive operations:
-- Instead of multiple queries, use JOINs
SELECT
t.TABLE_NAME,
t.TABLE_ROWS,
COUNT(c.COLUMN_NAME) as 'Column Count'
FROM information_schema.TABLES t
LEFT JOIN information_schema.COLUMNS c ON t.TABLE_NAME = c.TABLE_NAME
AND t.TABLE_SCHEMA = c.TABLE_SCHEMA
WHERE t.TABLE_SCHEMA = 'your_database'
GROUP BY t.TABLE_NAME;
Limitations and Considerations
What Information Schema Cannot Do
1. Data Modification:
- Cannot INSERT, UPDATE, or DELETE data
- Cannot CREATE or DROP objects
- Read-only access to metadata only
2. Real-time Accuracy:
- Some statistics may be cached or estimated
- TABLE_ROWS is often approximate for InnoDB tables
- Some data requires ANALYZE TABLE for accuracy
3. Permission Limitations:
- Shows only objects you have privileges to see
- Some system information requires SUPER privileges
- Sensitive data may be filtered based on user permissions
MariaDB vs MySQL Differences
MariaDB Extensions:
-- MariaDB-specific information_schema tables
SELECT * FROM information_schema.ALL_PLUGINS;
SELECT * FROM information_schema.SYSTEM_VARIABLES;
SELECT * FROM information_schema.SESSION_STATUS;
Version-specific Features:
- MySQL 8.0+ has additional information_schema tables
- MariaDB 10.x includes extra system information
- Always check your specific version capabilities
Practical Automation Examples
Backup Script Enhancement
#!/bin/bash
# Enhanced backup script using information_schema
DB_USER="username"
DB_PASS="password"
# Get list of user databases
DATABASES=$(mysql -u $DB_USER -p$DB_PASS -N -e "
SELECT SCHEMA_NAME
FROM information_schema.SCHEMATA
WHERE SCHEMA_NAME NOT IN ('information_schema', 'mysql', 'performance_schema', 'sys')
")
for DB in $DATABASES; do
echo "Backing up database: $DB"
# Get database size for progress estimation
SIZE=$(mysql -u $DB_USER -p$DB_PASS -N -e "
SELECT ROUND(SUM(DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024, 2)
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = '$DB'
")
echo "Database size: ${SIZE}MB"
mysqldump -u $DB_USER -p$DB_PASS $DB > "${DB}_backup_$(date +%Y%m%d).sql"
echo "Backup completed for $DB"
done
Database Documentation Generator
-- Generate CREATE TABLE statements for documentation
SELECT CONCAT(
'CREATE TABLE `', TABLE_NAME, '` (\n',
GROUP_CONCAT(
CONCAT(
' `', COLUMN_NAME, '` ',
UPPER(DATA_TYPE),
CASE
WHEN CHARACTER_MAXIMUM_LENGTH IS NOT NULL
THEN CONCAT('(', CHARACTER_MAXIMUM_LENGTH, ')')
WHEN NUMERIC_PRECISION IS NOT NULL
THEN CONCAT('(', NUMERIC_PRECISION,
CASE WHEN NUMERIC_SCALE > 0
THEN CONCAT(',', NUMERIC_SCALE)
ELSE '' END, ')')
ELSE ''
END,
CASE WHEN IS_NULLABLE = 'NO' THEN ' NOT NULL' ELSE '' END,
CASE WHEN COLUMN_DEFAULT IS NOT NULL
THEN CONCAT(' DEFAULT ', QUOTE(COLUMN_DEFAULT))
ELSE '' END,
CASE WHEN EXTRA != '' THEN CONCAT(' ', UPPER(EXTRA)) ELSE '' END
) ORDER BY ORDINAL_POSITION SEPARATOR ',\n'
),
'\n);'
) as 'CREATE Statement'
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'your_database_name'
GROUP BY TABLE_NAME
ORDER BY TABLE_NAME;
Conclusion
The Information Schema is an invaluable tool for database administrators, developers, and analysts working with MySQL and MariaDB databases. It provides comprehensive metadata access that enables:
Key Benefits:
- Database Introspection: Understanding your database structure without external tools
- Automation: Building scripts that adapt to schema changes
- Monitoring: Tracking database growth, performance, and health
- Documentation: Generating up-to-date schema documentation
- Analysis: Identifying optimization opportunities and structural issues
Best Practices for Usage:
- Always filter queries by specific database/schema names
- Use Information Schema data to build dynamic, adaptable applications
- Combine with regular database monitoring for comprehensive insights
- Keep in mind permission limitations and approximate statistics
- Test queries on development systems before running on production
Common Use Cases:
- Database migration and comparison tools
- Automated backup and maintenance scripts
- Security auditing and permission reviews
- Performance monitoring and optimization
- Dynamic application schema adaptation
The Information Schema bridges the gap between manual database inspection and automated database management, making it an essential component of any serious database administration toolkit. Whether you're managing a single website database or multiple enterprise applications, mastering Information Schema queries will significantly improve your database management capabilities.
Remember that Information Schema is your window into the database's metadata - use it wisely to build more robust, maintainable, and self-documenting database applications.