Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Menanyakan SKEMA INFORMASI MySQL:Mengapa? Bagaimana?

Basis data perlu berjalan secara optimal, tetapi itu bukan tugas yang mudah. Basis data SKEMA INFORMASI dapat menjadi senjata rahasia Anda dalam perang pengoptimalan basis data.

Kami terbiasa membuat database menggunakan antarmuka grafis atau serangkaian perintah SQL. Tidak apa-apa, tetapi juga bagus untuk memahami sedikit tentang apa yang terjadi di latar belakang. Ini penting untuk pembuatan, pemeliharaan, dan pengoptimalan database, dan juga merupakan cara yang baik untuk melacak perubahan yang terjadi 'di balik layar'.

Pada artikel ini, kita akan melihat beberapa kueri SQL yang dapat membantu Anda mengintip cara kerja database MySQL.

Basis Data INFORMATION_SCHEMA

Kita telah membahas INFORMATION_SCHEMA basis data dalam artikel ini. Jika Anda belum membacanya, saya pasti akan menyarankan Anda melakukannya sebelum melanjutkan.

Jika Anda membutuhkan penyegaran pada INFORMATION_SCHEMA database – atau jika Anda memutuskan untuk tidak membaca artikel pertama – berikut adalah beberapa fakta dasar yang perlu Anda ketahui:

  • INFORMATION_SCHEMA database adalah bagian dari standar ANSI. Kami akan bekerja dengan MySQL, tetapi RDBMS lain memiliki variannya. Anda dapat menemukan versi untuk Database H2, HSQLDB, MariaDB, Microsoft SQL Server, dan PostgreSQL.
  • Ini adalah database yang melacak semua database lain di server; kami akan menemukan deskripsi semua objek di sini.
  • Seperti basis data lainnya, INFORMATION_SCHEMA database berisi sejumlah tabel terkait dan informasi tentang objek yang berbeda.
  • Anda dapat membuat kueri database ini menggunakan SQL dan menggunakan hasilnya untuk:
    • Pantau status dan kinerja basis data, dan
    • Buat kode secara otomatis berdasarkan hasil kueri.

Sekarang mari kita beralih ke query database INFORMATION_SCHEMA. Kita akan mulai dengan melihat model data yang akan kita gunakan.

Model Data

Model yang akan kita gunakan dalam artikel ini ditunjukkan di bawah ini.




Ini adalah model yang disederhanakan yang memungkinkan kita untuk menyimpan informasi tentang kelas, instruktur, siswa, dan detail terkait lainnya. Mari kita membahas tabel secara singkat.

Kami akan menyimpan daftar instruktur di lecturer meja. Untuk setiap dosen, kami akan mencatat first_name dan last_name .

class tabel mencantumkan semua kelas yang kami miliki di sekolah kami. Untuk setiap record dalam tabel ini, kita akan menyimpan class_name , ID dosen, start_date yang direncanakan dan end_date , dan class_details tambahan apa pun . Demi kesederhanaan, saya akan berasumsi bahwa kita hanya memiliki satu dosen per kelas.

Kelas biasanya diselenggarakan sebagai rangkaian kuliah. Mereka umumnya membutuhkan satu atau lebih ujian. Kami akan menyimpan daftar kuliah dan ujian terkait di lecture dan exam tabel. Keduanya akan memiliki ID kelas terkait dan start_time yang diharapkan dan end_time .

Sekarang kami membutuhkan siswa untuk kelas kami. Daftar semua siswa disimpan di student meja. Sekali lagi, kami hanya akan menyimpan first_name dan last_name setiap siswa.

Hal terakhir yang perlu kita lakukan adalah melacak aktivitas siswa. Kami akan menyimpan daftar setiap kelas tempat siswa terdaftar, catatan kehadiran siswa, dan hasil ujian mereka. Masing-masing dari tiga tabel yang tersisa – on_class , on_lecture dan on_exam – akan memiliki referensi ke siswa dan referensi ke tabel yang sesuai. Hanya on_exam tabel akan memiliki nilai tambahan:nilai.

Ya, model ini sangat sederhana. Kita bisa menambahkan banyak detail lain tentang mahasiswa, dosen, dan kelas. Kami dapat menyimpan nilai historis ketika catatan diperbarui atau dihapus. Namun, model ini akan cukup untuk tujuan artikel ini.

Membuat Basis Data

Kami siap membuat database di server lokal kami dan memeriksa apa yang terjadi di dalamnya. Kami akan mengekspor model (di Vertabelo) menggunakan “Generate SQL script " tombol.

Kemudian kita akan membuat database pada instance MySQL Server. Saya memanggil database saya “classes_and_students ”.

Hal berikutnya yang perlu kita lakukan adalah menjalankan skrip SQL yang telah dibuat sebelumnya.

Sekarang kita memiliki database dengan semua objeknya (tabel, kunci utama dan kunci asing, kunci alternatif).

Ukuran Basis Data

Setelah script berjalan, data tentang “classes and students ” database disimpan di INFORMATION_SCHEMA basis data. Data ini ada di banyak tabel yang berbeda. Saya tidak akan mencantumkan semuanya lagi di sini; kami melakukannya di artikel sebelumnya.

Mari kita lihat bagaimana kita dapat menggunakan SQL standar pada database ini. Saya akan mulai dengan satu pertanyaan yang sangat penting:

SET @table_schema = "classes_and_students";

SELECT 

    ROUND(SUM( INFORMATION_SCHEMA.TABLES.DATA_LENGTH + INFORMATION_SCHEMA.TABLES.INDEX_LENGTH ) / 1024 / 1024, 2) AS "DB Size (in MB)",
    ROUND(SUM( INFORMATION_SCHEMA.TABLES.DATA_FREE )/ 1024 / 1024, 2) AS "Free Space (in MB)"
    
FROM INFORMATION_SCHEMA.TABLES
WHERE INFORMATION_SCHEMA.TABLES.TABLE_SCHEMA = @table_schema;

Kami hanya menanyakan INFORMATION_SCHEMA.TABLES meja di sini. Tabel ini seharusnya memberi kita lebih dari cukup detail tentang semua tabel di server. Harap perhatikan bahwa saya hanya memfilter tabel dari "classes_and_students " database menggunakan SET variabel di baris pertama dan kemudian menggunakan nilai ini dalam kueri. Sebagian besar tabel berisi kolom TABLE_NAME dan TABLE_SCHEMA , yang menunjukkan tabel dan skema/database milik data ini.

Kueri ini akan mengembalikan ukuran database kami saat ini dan ruang kosong yang disediakan untuk database kami. Inilah hasil sebenarnya:

Seperti yang diharapkan, ukuran database kosong kami kurang dari 1 MB, dan ruang kosong yang dipesan jauh lebih besar.

Ukuran dan Properti Tabel

Hal menarik berikutnya yang harus dilakukan adalah melihat ukuran tabel di database kita. Untuk melakukannya, kami akan menggunakan kueri berikut:

SET @table_schema = "classes_and_students";

SELECT 

	INFORMATION_SCHEMA.TABLES.TABLE_NAME,
    ROUND(SUM( INFORMATION_SCHEMA.TABLES.DATA_LENGTH + INFORMATION_SCHEMA.TABLES.INDEX_LENGTH ) / 1024 / 1024, 2) "Table Size (in MB)",
	ROUND(SUM( INFORMATION_SCHEMA.TABLES.DATA_FREE )/ 1024 / 1024, 2) AS "Free Space (in MB)",
	MAX( INFORMATION_SCHEMA.TABLES.TABLE_ROWS) AS table_rows_number,
	MAX( INFORMATION_SCHEMA.TABLES.AUTO_INCREMENT) AS auto_increment_value

FROM INFORMATION_SCHEMA.TABLES
WHERE INFORMATION_SCHEMA.TABLES.TABLE_SCHEMA = @table_schema
GROUP BY INFORMATION_SCHEMA.TABLES.TABLE_NAME
ORDER BY 2 DESC;

Kueri hampir identik dengan kueri sebelumnya, dengan satu pengecualian:hasilnya dikelompokkan pada tingkat tabel.

Berikut adalah gambar hasil yang dikembalikan oleh kueri ini:

Pertama, kita dapat melihat bahwa kedelapan tabel memiliki “Ukuran Tabel” minimal minimal dicadangkan untuk definisi tabel, yang mencakup kolom, kunci utama, dan indeks. “Ruang Kosong” didistribusikan secara merata di antara semua tabel.

Kita juga dapat melihat jumlah baris saat ini di setiap tabel dan nilai saat ini dari auto_increment properti untuk setiap tabel. Karena semua tabel benar-benar kosong, kami tidak memiliki data dan auto_increment diatur ke 1 (nilai yang akan ditetapkan ke baris yang disisipkan berikutnya).

Kunci Utama

Setiap tabel harus memiliki nilai kunci utama yang ditentukan, jadi sebaiknya periksa apakah ini benar untuk database kita. Salah satu cara untuk melakukannya adalah dengan menggabungkan daftar semua tabel dengan daftar batasan. Ini akan memberi kami info yang kami butuhkan.

SET @table_schema = "classes_and_students";

SELECT 

	tab.TABLE_NAME,
    COUNT(*) AS PRI_number

FROM INFORMATION_SCHEMA.TABLES tab
LEFT JOIN (
    SELECT

        INFORMATION_SCHEMA.COLUMNS.TABLE_SCHEMA,
        INFORMATION_SCHEMA.COLUMNS.TABLE_NAME

    FROM INFORMATION_SCHEMA.COLUMNS
    WHERE INFORMATION_SCHEMA.COLUMNS.TABLE_SCHEMA  = @table_schema
    AND INFORMATION_SCHEMA.COLUMNS.COLUMN_KEY = 'PRI'
) col 
	ON tab.TABLE_SCHEMA = col.TABLE_SCHEMA
    AND tab.TABLE_NAME = col.TABLE_NAME
WHERE tab.TABLE_SCHEMA = @table_schema
GROUP BY 
	tab.TABLE_NAME;

Kami juga menggunakan INFORMATION_SCHEMA.COLUMNS tabel dalam kueri ini. Sementara bagian pertama dari kueri hanya akan mengembalikan semua tabel dalam database, bagian kedua (setelah LEFT JOIN ) akan menghitung jumlah PRI dalam tabel ini. Kami menggunakan LEFT JOIN karena kita ingin melihat apakah sebuah tabel memiliki 0 PRI di COLUMNS tabel.

Seperti yang diharapkan, setiap tabel dalam database kami berisi tepat satu kolom kunci utama (PRI).

“Pulau”?

"Kepulauan" adalah tabel yang benar-benar terpisah dari model lainnya. Itu terjadi ketika tabel tidak berisi kunci asing dan tidak direferensikan di tabel lain mana pun. Ini seharusnya tidak terjadi kecuali ada alasan yang sangat bagus, mis. ketika tabel berisi parameter atau menyimpan hasil atau laporan di dalam model.

SET @table_schema = "classes_and_students";

SELECT 

	tab.TABLE_NAME,
    (CASE WHEN f1.number_referenced IS NULL THEN 0 ELSE f1.number_referenced END) AS number_referenced,
    (CASE WHEN f2.number_referencing IS NULL THEN 0 ELSE f2.number_referencing END) AS number_referencing

FROM INFORMATION_SCHEMA.TABLES tab
LEFT JOIN 

-- # table was used as a reference
(
    SELECT 
        INFORMATION_SCHEMA.KEY_COLUMN_USAGE.REFERENCED_TABLE_SCHEMA,
        INFORMATION_SCHEMA.KEY_COLUMN_USAGE.REFERENCED_TABLE_NAME,
        COUNT(*) AS number_referenced
    FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE 
    WHERE INFORMATION_SCHEMA.KEY_COLUMN_USAGE.REFERENCED_TABLE_SCHEMA = @table_schema
    GROUP BY
        INFORMATION_SCHEMA.KEY_COLUMN_USAGE.REFERENCED_TABLE_SCHEMA,
        INFORMATION_SCHEMA.KEY_COLUMN_USAGE.REFERENCED_TABLE_NAME
) f1 
	ON tab.TABLE_SCHEMA = f1.REFERENCED_TABLE_SCHEMA
    AND tab.TABLE_NAME = f1.REFERENCED_TABLE_NAME

LEFT JOIN

-- # of references in the table
(
    SELECT 
        INFORMATION_SCHEMA.KEY_COLUMN_USAGE.TABLE_SCHEMA,
        INFORMATION_SCHEMA.KEY_COLUMN_USAGE.TABLE_NAME,
        COUNT(*) AS number_referencing
    FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE 
    WHERE INFORMATION_SCHEMA.KEY_COLUMN_USAGE.REFERENCED_TABLE_SCHEMA = @table_schema
    AND INFORMATION_SCHEMA.KEY_COLUMN_USAGE.REFERENCED_TABLE_NAME IS NOT NULL
    GROUP BY
        INFORMATION_SCHEMA.KEY_COLUMN_USAGE.TABLE_SCHEMA,
        INFORMATION_SCHEMA.KEY_COLUMN_USAGE.TABLE_NAME
) f2 
	ON tab.TABLE_SCHEMA = f2.TABLE_SCHEMA
    AND tab.TABLE_NAME = f2.TABLE_NAME    
    
WHERE tab.TABLE_SCHEMA = @table_schema;

Apa ide di balik kueri ini? Nah, kami menggunakan INFORMATION_SCHEMA.KEY_COLUMN_USAGE tabel untuk menguji apakah ada kolom dalam tabel yang menjadi referensi ke tabel lain atau jika ada kolom yang digunakan sebagai referensi di tabel lain. Bagian pertama kueri memilih semua tabel. Setelah LEFT JOIN pertama, kami menghitung berapa kali kolom apa pun dari tabel ini digunakan sebagai referensi. Setelah LEFT JOIN kedua, kami menghitung berapa kali kolom mana pun dari tabel ini mereferensikan tabel lain.

Hasil yang dikembalikan adalah:

Di baris untuk class tabel, angka 3 dan 1 menunjukkan bahwa tabel ini dirujuk tiga kali (dalam lecture , exam , dan on_class tabel) dan berisi satu atribut yang mereferensikan tabel lain (lecturer_id ). Tabel lainnya mengikuti pola yang sama, meskipun angka sebenarnya tentu saja akan berbeda. Aturannya di sini adalah bahwa tidak ada baris yang harus memiliki 0 di kedua kolom.

Menambahkan Baris

Sejauh ini, semuanya berjalan seperti yang diharapkan. Kami telah berhasil mengimpor model data kami dari Vertabelo ke Server MySQL lokal. Semua tabel berisi kunci, seperti yang kita inginkan, dan semua tabel terkait satu sama lain – tidak ada “pulau” dalam model kita.

Sekarang, kami akan menyisipkan beberapa baris di tabel kami dan menggunakan kueri yang ditunjukkan sebelumnya untuk melacak perubahan dalam database kami.

Setelah menambahkan 1.000 baris di tabel dosen, kita akan menjalankan lagi query dari “Table Sizes and Properties " bagian. Ini akan mengembalikan hasil berikut:

Kita dapat dengan mudah melihat bahwa jumlah baris dan nilai auto_increment telah berubah seperti yang diharapkan, tetapi tidak ada perubahan signifikan dalam ukuran tabel.

Ini hanya contoh tes; dalam situasi kehidupan nyata, kita akan melihat perubahan yang signifikan. Jumlah baris akan berubah drastis dalam tabel yang diisi oleh pengguna atau proses otomatis (yaitu tabel yang bukan kamus). Memeriksa ukuran dan nilai dalam tabel tersebut adalah cara yang sangat baik untuk menemukan dan memperbaiki perilaku yang tidak diinginkan dengan cepat.

Mau Berbagi?

Bekerja dengan database adalah upaya konstan untuk kinerja yang optimal. Agar lebih berhasil dalam pengejaran itu, Anda harus menggunakan alat apa pun yang tersedia. Hari ini kami telah melihat beberapa kueri yang berguna dalam perjuangan kami untuk kinerja yang lebih baik. Apakah Anda menemukan hal lain yang berguna? Sudahkah Anda bermain dengan INFORMATION_SCHEMA basis data sebelumnya? Bagikan pengalaman Anda di komentar di bawah.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cara Mendapatkan Data Setiap Jam di MySQL

  2. Sisipkan Query Untuk Menyisipkan Baris di MySQL

  3. Apa Nama Batasan Default di MySQL?

  4. Temukan nilai paling sering di kolom SQL

  5. Kesalahan saat menggunakan kecuali dalam kueri