MySQL وتصميم قواعد البيانات

مخطط المعلومات والبيانات الوصفية (Information Schema & Metadata)

13 دقيقة الدرس 25 من 40

مخطط المعلومات والبيانات الوصفية (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 ;

تمرين عملي:

إنشاء منشئ وثائق قاعدة بيانات:

  1. أنشئ إجراءً مخزناً ينشئ وثائق شاملة لقاعدة بيانات بما في ذلك:
    • قائمة بجميع الجداول مع عدد الصفوف والأحجام
    • جميع الأعمدة مع أنواع البيانات والقيود
    • جميع الفهارس وأعمدتها
    • جميع علاقات المفاتيح الأجنبية
    • جميع الإجراءات المخزنة والدوال
    • جميع المشغلات والأحداث
  2. خزن الوثائق في جدول 'database_documentation'
  3. قم بتضمين الطابع الزمني للإنشاء وإصدار قاعدة البيانات
  4. اختبره على قاعدة البيانات الحالية الخاصة بك

جداول مخطط المعلومات المهمة

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
  • مخطط المعلومات ضروري لإدارة قاعدة البيانات
الوحدة مكتملة! لقد أتقنت كائنات قاعدة البيانات المتقدمة بما في ذلك طرق العرض والإجراءات المخزنة والدوال والمشغلات والأحداث والمؤشرات ومخطط المعلومات. هذه الأدوات القوية تمكّن أتمتة وإدارة قاعدة البيانات المتطورة!