Aplikasi saya tergantung pada menjalankan "tampilkan kolom" untuk tabel tertentu. Dibutuhkan sekitar 60 ms untuk dijalankan, sedangkan semua kueri kami yang lain menggunakan ms. Meminta information_schema
secara langsung bahkan lebih lambat.
Basis data berisi sekitar 250 basis data, dengan 100 hingga 200 tabel per basis data (total sekitar 20 ribu tabel).
- Bagaimana saya bisa mengetahui mengapa operasi ini sangat lambat?
- Apakah mungkin ada beberapa pengaturan yang dapat saya ubah untuk membuatnya berjalan lebih cepat, atau untuk menyimpannya di sisi SQL?
(Aplikasi ini melakukan sekitar 14 pertanyaan seperti itu per memuat halaman - Saya sangat menyadari bahwa kode warisan ini perlu dibersihkan, tetapi mencari opsi yang mungkin saat saya bekerja pada perbaikan jangka panjang.)
Jawaban:
MySQL menghitung ulang statistik tabel untuk operasi tertentu yang mengakses
INFORMATION_SCHEMA
tabel (SHOW COLUMNS
hanya alias yang mudah untuk queryINFORMATION_SCHEMA.COLUMNS
). Tetapkan innodb_stats_on_metadata menjadi false, yang akan mencegah penghitungan ulang ini terjadi ketika Anda meminta metadata dari tabel.dan tambahkan yang berikut ke
my.cnf
sumber
[mysqld]
sana. Mungkin jelas bagi banyak orang bahwa pengaturan ini akan dilakukan di bawah mysqld, tetapi mungkin tidak jelas bagi mereka yang akan menanyakan pertanyaan ini. By the way, ini dipercepatSELECT COUNT(*)
di salah satuinformation_schema
meja saya menjadi 6 detik dari lebih dari satu menit. Masih lambat, tetapi peningkatan besar.Saya sarankan Anda membuat database yang memiliki
INFORMATION_SCHEMA
tabel (atau hanya yang Anda butuhkan) sebagai duplikat. Indeks mereka dengan tepat dan Anda akan mendapatkan keuntungan kinerja.Masalah sinkronisasi antara database ini dan
INFORMATION_SCHEMA
itu rumit.Anda bisa memiliki prosedur yang menyinkronkan tabel ini setiap jam atau setiap 5 menit (seberapa sering struktur tabel berubah?).
Gagasan lain adalah menggunakan MySQL Proxy untuk menangkap
ALTER TABLE
pernyataan apa pun (danCREATE
danDROP
danCREATE INDEX
dan pernyataan apa pun lainnya yang mengubah informasi yang Anda butuhkan) dan kemudian menyinkronkan skema informasi yang direplikasi setelah pernyataan ini berhasil.Jika Anda hanya memerlukan nama kolom dan bukan informasi lain, seperti tipe data, panjang, atau indeks yang tersedia, Anda mungkin dapat mengganti penggunaan
SHOW COLUMNS
dengan kueri (cepat) yang menghasilkan 1 baris saja, denganLIMIT 1
atau tidak sama sekali, dengan salah satuLIMIT 0
atau:Terlepas dari saran umum yang menentang penggunaan
SELECT *
, ini mungkin merupakan kasus yang sah di mana tidak ada hal lain yang berguna. (yang lainnya kecuali*
, dapat menyebabkan kesalahan!)sumber
Dalam kasus khusus ini, saya pikir
INFORMATION_SCHEMA
ini adalah herring merah. Dari tesSHOW COLUMNS
kinerja saya sendiri ,innodb_stats_on_metadata
variabel tampaknya tidak membuat perbedaan pada tabel MyISAM atau InnoDB.Namun, dari manual MySQL 5.0 ...
Ini tampaknya telah dihapus dari manual pada MySQL 5.5, tetapi masih berlaku untuk versi itu ...
Informasi bidang yang dikembalikan dengan set hasil kueri berisi informasi yang sama dengan yang dikembalikan oleh
SHOW COLUMNS
, sehinggaSELECT * FROM my_table LIMIT 0
harus mencapai hal yang sama tanpa membuat tabel sementara di-disk per kueri.Contoh cepat untuk hanya mengambil nama bidang dalam PHP ...
Mengambil info bidang dengan cara ini sedikit lebih canggung untuk diterjemahkan. Anda harus berkonsultasi dengan deskripsi
MYSQL_FIELD
struktur yang mendasarinya untuk mengeluarkan tipe data dan flag, tetapi itu berjalan sekitar 7 kali lebih cepat pada sistem saya.sumber
Saya suka saran pertama dalam jawaban @ yerpcube (+1), tapi saya ingin mengusulkan sesuatu
--no-data
--routines
--triggers
--all-databases
atau--databases
diikuti oleh daftar basis data yang Anda inginkanDengan demikian, Anda mysqldump akan terlihat sebagai berikut:
Itu dia. Ke depan, yang perlu Anda lakukan adalah menyambung ke instance database port 3307 ini dan menjalankan kueri terkait skema apa pun dengan isi hati Anda. Jika Anda tahu ada tabel di database produksi yang berubah, cukup masukkan mysqldump skema dari produksi dan muat ulang lagi ke port 3307 misalnya.
PERINGATAN: Jika Anda menginstal instance mysql pada mesin yang sama dengan produksi, pastikan Anda terhubung ke instance tersebut menggunakan
Jika Anda mengeksekusi
Itu akan selang produksi. Jadi, HATI-HATI !!!!
Alternatifnya adalah dengan hanya menggunakan server DB yang terpisah.
sumber