MySQL وتصميم قواعد البيانات
مخطط المعلومات والبيانات الوصفية (Information Schema & Metadata)
مخطط المعلومات والبيانات الوصفية (Information Schema & Metadata)
مخطط المعلومات هو قاعدة بيانات خاصة توفر الوصول إلى البيانات الوصفية لقاعدة البيانات - معلومات حول هيكل قاعدة البيانات والجداول والأعمدة والفهارس والمزيد. إنه مفيد بشكل لا يصدق للفحص الذاتي لقاعدة البيانات وإنشاء الوثائق وبناء أدوات قاعدة البيانات الديناميكية. في هذا الدرس، سنستكشف كيفية الاستعلام واستخدام هذا المورد القوي.
ما هو مخطط المعلومات؟
مخطط المعلومات هو قاعدة بيانات للقراءة فقط يحتفظ بها MySQL تلقائياً. يحتوي على بيانات وصفية حول جميع قواعد البيانات والجداول والأعمدة والامتيازات الأخرى والمزيد.
مفهوم أساسي: يستخدم مخطط المعلومات طرق عرض SQL ANSI موحدة، مما يجعل استعلاماتك قابلة للنقل عبر أنظمة قواعد البيانات المختلفة (مع تعديلات طفيفة).
الوصول إلى مخطط المعلومات
-- سرد جميع قواعد البيانات
SELECT SCHEMA_NAME
FROM information_schema.SCHEMATA
ORDER BY SCHEMA_NAME;
-- الحصول على حجم قاعدة البيانات
SELECT
SCHEMA_NAME AS 'Database',
ROUND(SUM(DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024, 2) AS 'Size (MB)'
FROM information_schema.TABLES
GROUP BY SCHEMA_NAME
ORDER BY SUM(DATA_LENGTH + INDEX_LENGTH) DESC;
-- إظهار جميع جداول مخطط المعلومات
SHOW TABLES FROM information_schema;
الاستعلام عن معلومات الجدول
احصل على معلومات مفصلة حول الجداول في قاعدة البيانات الخاصة بك:
-- سرد جميع الجداول في قاعدة بيانات محددة
SELECT
TABLE_NAME,
TABLE_TYPE,
ENGINE,
TABLE_ROWS,
AVG_ROW_LENGTH,
ROUND((DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024, 2) AS 'Size (MB)',
TABLE_COLLATION,
CREATE_TIME,
UPDATE_TIME
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'your_database'
ORDER BY (DATA_LENGTH + INDEX_LENGTH) DESC;
-- العثور على أكبر الجداول
SELECT
TABLE_NAME,
ROUND((DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024, 2) AS 'Size (MB)',
TABLE_ROWS,
ROUND((DATA_LENGTH + INDEX_LENGTH) / TABLE_ROWS, 2) AS 'Bytes per Row'
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'your_database'
AND TABLE_ROWS > 0
ORDER BY (DATA_LENGTH + INDEX_LENGTH) DESC
LIMIT 10;
-- العثور على الجداول بدون مفتاح أساسي
SELECT TABLE_NAME
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'your_database'
AND TABLE_TYPE = 'BASE TABLE'
AND TABLE_NAME NOT IN (
SELECT TABLE_NAME
FROM information_schema.TABLE_CONSTRAINTS
WHERE CONSTRAINT_TYPE = 'PRIMARY KEY'
AND TABLE_SCHEMA = 'your_database'
);
معلومات الأعمدة
-- سرد جميع الأعمدة في جدول
SELECT
COLUMN_NAME,
COLUMN_TYPE,
IS_NULLABLE,
COLUMN_KEY,
COLUMN_DEFAULT,
EXTRA,
COLUMN_COMMENT
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'your_database'
AND TABLE_NAME = 'customers'
ORDER BY ORDINAL_POSITION;
-- العثور على جميع الأعمدة بنوع بيانات محدد
SELECT
TABLE_NAME,
COLUMN_NAME,
COLUMN_TYPE
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'your_database'
AND DATA_TYPE = 'varchar'
ORDER BY TABLE_NAME, ORDINAL_POSITION;
-- العثور على جميع أعمدة TEXT/BLOB (كثيفة الذاكرة)
SELECT
TABLE_NAME,
COLUMN_NAME,
COLUMN_TYPE
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'your_database'
AND DATA_TYPE IN ('text', 'mediumtext', 'longtext', 'blob', 'mediumblob', 'longblob')
ORDER BY TABLE_NAME;
-- العثور على الأعمدة بقيم NULL
SELECT
TABLE_NAME,
COLUMN_NAME,
IS_NULLABLE
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'your_database'
AND IS_NULLABLE = 'YES'
AND COLUMN_KEY != 'PRI'
ORDER BY TABLE_NAME, COLUMN_NAME;
معلومات الفهارس
-- إظهار جميع الفهارس في قاعدة بيانات
SELECT
TABLE_NAME,
INDEX_NAME,
GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX) AS COLUMNS,
INDEX_TYPE,
NON_UNIQUE,
NULLABLE,
COMMENT
FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = 'your_database'
GROUP BY TABLE_NAME, INDEX_NAME, INDEX_TYPE, NON_UNIQUE, NULLABLE, COMMENT
ORDER BY TABLE_NAME, INDEX_NAME;
-- العثور على الفهارس المكررة
SELECT
s1.TABLE_NAME,
s1.INDEX_NAME AS Index1,
s2.INDEX_NAME AS Index2,
GROUP_CONCAT(s1.COLUMN_NAME ORDER BY s1.SEQ_IN_INDEX) AS Columns
FROM information_schema.STATISTICS s1
JOIN information_schema.STATISTICS s2
ON s1.TABLE_SCHEMA = s2.TABLE_SCHEMA
AND s1.TABLE_NAME = s2.TABLE_NAME
AND s1.SEQ_IN_INDEX = s2.SEQ_IN_INDEX
AND s1.COLUMN_NAME = s2.COLUMN_NAME
AND s1.INDEX_NAME < s2.INDEX_NAME
WHERE s1.TABLE_SCHEMA = 'your_database'
GROUP BY s1.TABLE_NAME, s1.INDEX_NAME, s2.INDEX_NAME
HAVING COUNT(*) = (
SELECT COUNT(*)
FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = s1.TABLE_SCHEMA
AND TABLE_NAME = s1.TABLE_NAME
AND INDEX_NAME = s1.INDEX_NAME
);
-- العثور على الجداول بدون فهارس
SELECT TABLE_NAME
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'your_database'
AND TABLE_TYPE = 'BASE TABLE'
AND TABLE_NAME NOT IN (
SELECT DISTINCT TABLE_NAME
FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = 'your_database'
);
معلومات القيود
-- إظهار جميع المفاتيح الأجنبية
SELECT
CONSTRAINT_NAME,
TABLE_NAME,
COLUMN_NAME,
REFERENCED_TABLE_NAME,
REFERENCED_COLUMN_NAME
FROM information_schema.KEY_COLUMN_USAGE
WHERE TABLE_SCHEMA = 'your_database'
AND REFERENCED_TABLE_NAME IS NOT NULL
ORDER BY TABLE_NAME, CONSTRAINT_NAME;
-- الحصول على معلومات القيود التفصيلية
SELECT
tc.CONSTRAINT_NAME,
tc.TABLE_NAME,
tc.CONSTRAINT_TYPE,
kcu.COLUMN_NAME,
rc.UPDATE_RULE,
rc.DELETE_RULE
FROM information_schema.TABLE_CONSTRAINTS tc
LEFT JOIN information_schema.KEY_COLUMN_USAGE kcu
ON tc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME
AND tc.TABLE_SCHEMA = kcu.TABLE_SCHEMA
LEFT JOIN information_schema.REFERENTIAL_CONSTRAINTS rc
ON tc.CONSTRAINT_NAME = rc.CONSTRAINT_NAME
AND tc.TABLE_SCHEMA = rc.CONSTRAINT_SCHEMA
WHERE tc.TABLE_SCHEMA = 'your_database'
AND tc.CONSTRAINT_TYPE IN ('PRIMARY KEY', 'FOREIGN KEY', 'UNIQUE')
ORDER BY tc.TABLE_NAME, tc.CONSTRAINT_TYPE;
-- العثور على المفاتيح الأجنبية اليتيمة (تشير إلى جداول غير موجودة)
SELECT
kcu.TABLE_NAME,
kcu.COLUMN_NAME,
kcu.REFERENCED_TABLE_NAME,
kcu.REFERENCED_COLUMN_NAME
FROM information_schema.KEY_COLUMN_USAGE kcu
LEFT JOIN information_schema.TABLES t
ON kcu.REFERENCED_TABLE_NAME = t.TABLE_NAME
AND kcu.TABLE_SCHEMA = t.TABLE_SCHEMA
WHERE kcu.TABLE_SCHEMA = 'your_database'
AND kcu.REFERENCED_TABLE_NAME IS NOT NULL
AND t.TABLE_NAME IS NULL;
معلومات المستخدم والامتيازات
-- سرد جميع المستخدمين
SELECT
User,
Host,
account_locked,
password_expired
FROM mysql.user
ORDER BY User, Host;
-- إظهار امتيازات المستخدم
SELECT
GRANTEE,
PRIVILEGE_TYPE,
IS_GRANTABLE
FROM information_schema.USER_PRIVILEGES
WHERE GRANTEE LIKE '%username%'
ORDER BY PRIVILEGE_TYPE;
-- إظهار امتيازات على مستوى قاعدة البيانات
SELECT
GRANTEE,
TABLE_SCHEMA,
PRIVILEGE_TYPE
FROM information_schema.SCHEMA_PRIVILEGES
WHERE TABLE_SCHEMA = 'your_database'
ORDER BY GRANTEE, PRIVILEGE_TYPE;
-- إظهار امتيازات على مستوى الجدول
SELECT
GRANTEE,
TABLE_SCHEMA,
TABLE_NAME,
PRIVILEGE_TYPE
FROM information_schema.TABLE_PRIVILEGES
WHERE TABLE_SCHEMA = 'your_database'
ORDER BY TABLE_NAME, GRANTEE;
معلومات الإجراءات المخزنة
-- سرد جميع الإجراءات المخزنة والدوال
SELECT
ROUTINE_NAME,
ROUTINE_TYPE,
DATA_TYPE,
ROUTINE_DEFINITION,
CREATED,
LAST_ALTERED
FROM information_schema.ROUTINES
WHERE ROUTINE_SCHEMA = 'your_database'
ORDER BY ROUTINE_TYPE, ROUTINE_NAME;
-- العثور على الإجراءات بمعامل محدد
SELECT
SPECIFIC_NAME AS ROUTINE_NAME,
PARAMETER_NAME,
DATA_TYPE,
PARAMETER_MODE
FROM information_schema.PARAMETERS
WHERE SPECIFIC_SCHEMA = 'your_database'
ORDER BY SPECIFIC_NAME, ORDINAL_POSITION;
-- سرد جميع المشغلات
SELECT
TRIGGER_NAME,
EVENT_MANIPULATION,
EVENT_OBJECT_TABLE,
ACTION_TIMING,
ACTION_STATEMENT
FROM information_schema.TRIGGERS
WHERE TRIGGER_SCHEMA = 'your_database'
ORDER BY EVENT_OBJECT_TABLE, ACTION_TIMING;
-- سرد جميع الأحداث
SELECT
EVENT_NAME,
EVENT_DEFINITION,
INTERVAL_VALUE,
INTERVAL_FIELD,
STATUS,
STARTS,
ENDS,
LAST_EXECUTED
FROM information_schema.EVENTS
WHERE EVENT_SCHEMA = 'your_database'
ORDER BY EVENT_NAME;
إنشاء الوثائق
-- إنشاء وثائق شاملة للجدول
SELECT
t.TABLE_NAME,
t.ENGINE,
t.TABLE_ROWS,
ROUND((t.DATA_LENGTH + t.INDEX_LENGTH) / 1024 / 1024, 2) AS 'Size_MB',
t.TABLE_COMMENT,
GROUP_CONCAT(
CONCAT(
c.COLUMN_NAME, ' ',
c.COLUMN_TYPE,
IF(c.IS_NULLABLE = 'NO', ' NOT NULL', ''),
IF(c.COLUMN_KEY = 'PRI', ' PRIMARY KEY', ''),
IF(c.COLUMN_KEY = 'UNI', ' UNIQUE', ''),
IF(c.EXTRA != '', CONCAT(' ', c.EXTRA), '')
)
ORDER BY c.ORDINAL_POSITION
SEPARATOR '\n'
) AS COLUMNS
FROM information_schema.TABLES t
JOIN information_schema.COLUMNS c
ON t.TABLE_SCHEMA = c.TABLE_SCHEMA
AND t.TABLE_NAME = c.TABLE_NAME
WHERE t.TABLE_SCHEMA = 'your_database'
AND t.TABLE_TYPE = 'BASE TABLE'
GROUP BY t.TABLE_NAME, t.ENGINE, t.TABLE_ROWS, t.DATA_LENGTH, t.INDEX_LENGTH, t.TABLE_COMMENT
ORDER BY t.TABLE_NAME;
حالات الاستخدام الواقعية
-- 1. فحص صحة قاعدة البيانات
CREATE VIEW db_health_check AS
SELECT
'جداول بدون مفتاح أساسي' AS issue,
COUNT(*) AS count
FROM information_schema.TABLES t
WHERE TABLE_SCHEMA = 'your_database'
AND TABLE_TYPE = 'BASE TABLE'
AND NOT EXISTS (
SELECT 1 FROM information_schema.TABLE_CONSTRAINTS tc
WHERE tc.TABLE_SCHEMA = t.TABLE_SCHEMA
AND tc.TABLE_NAME = t.TABLE_NAME
AND tc.CONSTRAINT_TYPE = 'PRIMARY KEY'
)
UNION ALL
SELECT
'جداول بدون فهارس',
COUNT(DISTINCT t.TABLE_NAME)
FROM information_schema.TABLES t
LEFT JOIN information_schema.STATISTICS s
ON t.TABLE_SCHEMA = s.TABLE_SCHEMA
AND t.TABLE_NAME = s.TABLE_NAME
WHERE t.TABLE_SCHEMA = 'your_database'
AND t.TABLE_TYPE = 'BASE TABLE'
AND s.INDEX_NAME IS NULL
UNION ALL
SELECT
'أعمدة TEXT/BLOB كبيرة',
COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'your_database'
AND DATA_TYPE IN ('mediumtext', 'longtext', 'mediumblob', 'longblob');
-- 2. إنشاء عبارات CREATE TABLE
DELIMITER //
CREATE PROCEDURE generate_create_statement(IN tbl_name VARCHAR(64))
BEGIN
SELECT CONCAT(
'CREATE TABLE `', tbl_name, '` (\n',
GROUP_CONCAT(
CONCAT(
' `', COLUMN_NAME, '` ',
COLUMN_TYPE,
IF(IS_NULLABLE = 'NO', ' NOT NULL', ' NULL'),
IF(COLUMN_DEFAULT IS NOT NULL, CONCAT(' DEFAULT \'', COLUMN_DEFAULT, '\''), ''),
IF(EXTRA != '', CONCAT(' ', EXTRA), '')
)
ORDER BY ORDINAL_POSITION
SEPARATOR ',\n'
),
'\n);')
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = tbl_name;
END //
DELIMITER ;
-- 3. العثور على هياكل جداول متشابهة
SELECT
t1.TABLE_NAME AS table1,
t2.TABLE_NAME AS table2,
COUNT(*) AS matching_columns
FROM information_schema.COLUMNS t1
JOIN information_schema.COLUMNS t2
ON t1.COLUMN_NAME = t2.COLUMN_NAME
AND t1.DATA_TYPE = t2.DATA_TYPE
AND t1.TABLE_NAME < t2.TABLE_NAME
WHERE t1.TABLE_SCHEMA = 'your_database'
AND t2.TABLE_SCHEMA = 'your_database'
GROUP BY t1.TABLE_NAME, t2.TABLE_NAME
HAVING COUNT(*) > 5
ORDER BY matching_columns DESC;
-- 4. تحليل محرك التخزين
SELECT
ENGINE,
COUNT(*) AS table_count,
ROUND(SUM(DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024, 2) AS 'Total Size (MB)'
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'your_database'
GROUP BY ENGINE
ORDER BY SUM(DATA_LENGTH + INDEX_LENGTH) DESC;
تحليل الأداء
-- العثور على الجداول التي تحتاج إلى تحسين
SELECT
TABLE_NAME,
ENGINE,
ROUND((DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024, 2) AS 'Size (MB)',
ROUND(DATA_FREE / 1024 / 1024, 2) AS 'Free Space (MB)',
ROUND((DATA_FREE / (DATA_LENGTH + INDEX_LENGTH)) * 100, 2) AS 'Fragmentation %'
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'your_database'
AND DATA_FREE > 0
ORDER BY DATA_FREE DESC;
-- تحديد الفهارس غير المستخدمة (يتطلب مخطط sys)
SELECT
t.TABLE_SCHEMA,
t.TABLE_NAME,
s.INDEX_NAME,
ROUND((s.STAT_VALUE * @@innodb_page_size) / 1024 / 1024, 2) AS 'Index Size (MB)'
FROM information_schema.TABLES t
JOIN information_schema.STATISTICS s
ON t.TABLE_SCHEMA = s.TABLE_SCHEMA
AND t.TABLE_NAME = s.TABLE_NAME
JOIN information_schema.INNODB_SYS_TABLESTATS ist
ON CONCAT(t.TABLE_SCHEMA, '/', t.TABLE_NAME) = ist.NAME
WHERE t.TABLE_SCHEMA = 'your_database'
AND s.INDEX_NAME != 'PRIMARY'
GROUP BY t.TABLE_SCHEMA, t.TABLE_NAME, s.INDEX_NAME;
بناء أدوات ديناميكية
DELIMITER //
-- إجراء لنسخ احتياطي لجميع الجداول ديناميكياً
CREATE PROCEDURE backup_all_tables()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE tbl_name VARCHAR(64);
DECLARE backup_cursor CURSOR FOR
SELECT TABLE_NAME
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_TYPE = 'BASE TABLE';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN backup_cursor;
backup_loop: LOOP
FETCH backup_cursor INTO tbl_name;
IF done THEN
LEAVE backup_loop;
END IF;
-- إنشاء جدول نسخ احتياطي
SET @sql = CONCAT('CREATE TABLE ', tbl_name, '_backup AS SELECT * FROM ', tbl_name);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END LOOP;
CLOSE backup_cursor;
END //
-- إنشاء خريطة علاقات شبيهة بـ ERD
CREATE PROCEDURE show_table_relationships()
BEGIN
SELECT
CONCAT(kcu.TABLE_NAME, '.', kcu.COLUMN_NAME) AS 'Foreign Key',
CONCAT(kcu.REFERENCED_TABLE_NAME, '.', kcu.REFERENCED_COLUMN_NAME) AS 'References',
rc.UPDATE_RULE,
rc.DELETE_RULE
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.TABLE_SCHEMA = DATABASE()
AND kcu.REFERENCED_TABLE_NAME IS NOT NULL
ORDER BY kcu.TABLE_NAME, kcu.COLUMN_NAME;
END //
DELIMITER ;
تمرين عملي:
إنشاء منشئ وثائق قاعدة بيانات:
- أنشئ إجراءً مخزناً ينشئ وثائق شاملة لقاعدة بيانات بما في ذلك:
- قائمة بجميع الجداول مع عدد الصفوف والأحجام
- جميع الأعمدة مع أنواع البيانات والقيود
- جميع الفهارس وأعمدتها
- جميع علاقات المفاتيح الأجنبية
- جميع الإجراءات المخزنة والدوال
- جميع المشغلات والأحداث
- خزن الوثائق في جدول 'database_documentation'
- قم بتضمين الطابع الزمني للإنشاء وإصدار قاعدة البيانات
- اختبره على قاعدة البيانات الحالية الخاصة بك
جداول مخطط المعلومات المهمة
SCHEMATA - معلومات قاعدة البيانات
TABLES - البيانات الوصفية للجدول
COLUMNS - تفاصيل الأعمدة
STATISTICS - معلومات الفهارس
TABLE_CONSTRAINTS - تعريفات القيود
KEY_COLUMN_USAGE - علاقات المفاتيح الأجنبية
REFERENTIAL_CONSTRAINTS - قواعد تحديث/حذف المفاتيح الأجنبية
ROUTINES - الإجراءات المخزنة/الدوال
PARAMETERS - معاملات الإجراءات
TRIGGERS - تعريفات المشغلات
EVENTS - الأحداث المجدولة
USER_PRIVILEGES - أذونات المستخدم
SCHEMA_PRIVILEGES - أذونات قاعدة البيانات
TABLE_PRIVILEGES - أذونات الجدول
VIEWS - تعريفات طرق العرض
PARTITIONS - معلومات تقسيم الجدول
ENGINES - محركات التخزين المتاحة
أفضل الممارسات
✓ استخدم مخطط المعلومات للفحص الذاتي لقاعدة البيانات
✓ إنشاء الوثائق تلقائياً
✓ مراقبة صحة قاعدة البيانات بانتظام
✓ تحديد فرص التحسين
✓ بناء أدوات قاعدة بيانات ديناميكية
✓ توثيق تغييرات المخطط
✓ مراجعة الأمان والامتيازات
✓ مقارنة مخططات التطوير مقابل الإنتاج
✗ لا تستعلم عن مخطط المعلومات بشكل متكرر جداً
✗ تجنب الانضمامات المعقدة على مخطط المعلومات
✗ لا تعتمد على مخطط المعلومات للبيانات في الوقت الفعلي
الملخص
في هذا الدرس، تعلمت:
- يوفر مخطط المعلومات بيانات وصفية عن قاعدة البيانات الخاصة بك
- الاستعلام عن الجداول والأعمدة والفهارس والقيود برمجياً
- إنشاء الوثائق تلقائياً من البيانات الوصفية للمخطط
- تحديد مشاكل صحة قاعدة البيانات وفرص التحسين
- بناء أدوات قاعدة بيانات ديناميكية باستخدام معلومات المخطط
- مراجعة امتيازات المستخدم وإعدادات الأمان
- إنشاء استعلامات قابلة للنقل باستخدام معايير ANSI SQL
- مخطط المعلومات ضروري لإدارة قاعدة البيانات
الوحدة مكتملة! لقد أتقنت كائنات قاعدة البيانات المتقدمة بما في ذلك طرق العرض والإجراءات المخزنة والدوال والمشغلات والأحداث والمؤشرات ومخطط المعلومات. هذه الأدوات القوية تمكّن أتمتة وإدارة قاعدة البيانات المتطورة!