Saya membuat banyak penelitian tentang cara mempertahankan indeks di MySQL untuk mencegah fragmentasi dan untuk mengoptimalkan entah bagaimana pelaksanaan beberapa pertanyaan.
Saya kenal dengan rumus yang menghitung rasio antara ruang maks yang tersedia untuk tabel VS ruang yang digunakan oleh data dan indeks.
Namun pertanyaan utama saya masih belum terjawab. Mungkin ini disebabkan oleh fakta bahwa saya terbiasa dengan pemeliharaan indeks di SQL Server, dan saya cenderung berpikir bahwa di MySQL itu harus serupa.
Di SQL server, Anda dapat memiliki beberapa indeks, dan masing-masingnya dapat memiliki tingkat fragmentasi yang berbeda. Kemudian Anda dapat mengambil satu dan melakukan operasi 'REORGANIZE' atau 'REBUILD' dalam indeks tertentu, tanpa mempengaruhi sisanya.
Sepengetahuan saya, tidak ada 'tabel fragmentasi' seperti itu, dan SQL Server tidak menyediakan alat untuk memperbaiki 'tabel fragmentasi'. Apa yang disediakannya adalah alat untuk memeriksa fragmentasi indeks (dipahami seperti rasio antara jumlah halaman yang digunakan oleh indeks VS kepenuhan halaman itu dan kedekatan), serta fragmentasi internal dan eksternal.
Semua itu cukup mudah dimengerti, setidaknya bagi saya.
Sekarang, ketika tiba giliran untuk mempertahankan indeks di MySQL, hanya ada konsep fragmentasi tabel, seperti yang disebutkan di atas.
Sebuah tabel di MySQL dapat memiliki beberapa indeks, tetapi ketika saya memeriksa 'rasio fragmentasi' dengan rumus terkenal itu, saya tidak melihat fragmentasi dari setiap indeks, tetapi tabel secara keseluruhan.
Ketika saya ingin mengoptimalkan indeks di MySQL, saya tidak memilih indeks tertentu untuk beroperasi (seperti dalam SQL Server). Sebagai gantinya, saya melakukan operasi 'MENGOPTIMALKAN' di seluruh tabel, yang mungkin mempengaruhi semua indeks.
Ketika tabel dioptimalkan dalam MySQL, rasio antara ruang yang digunakan oleh data + indeks VS ruang keseluruhan berkurang, yang menyarankan beberapa jenis pengorganisasian ulang fisik dalam hard drive, yang diterjemahkan menjadi pengurangan ruang fisik. Namun, indeks fragmentasi tidak hanya tentang ruang fisik, tetapi struktur pohon yang telah berubah seiring waktu karena sisipan dan pembaruan.
Akhirnya, saya mendapat meja di InnoDB / MySQL. Tabel itu memiliki 3 juta catatan, 105 kolom, dan 55 indeks. Ini adalah 1.5GB tidak termasuk indeks, yang 2.1GB.
Tabel itu dipukul ribuan kali setiap hari untuk memperbarui, penyisipan (kami tidak benar-benar menghapus catatan).
Tabel itu telah dibuat bertahun-tahun dan saya tahu pasti tidak ada yang mempertahankan indeks apa pun.
Saya mengharapkan untuk menemukan fragmentasi besar di sana, tetapi ketika saya melakukan perhitungan fragmentasi seperti yang ditentukan
free_space / (data_length + index_length)
ternyata saya hanya memiliki 0,2% fragmentasi. IMHO itu cukup tidak realistis.
Jadi pertanyaan besarnya adalah:
- Bagaimana cara memeriksa fragmentasi indeks tertentu di MySQL, bukan tabel secara keseluruhan
- Apakah OPTIMIZE TABLE benar-benar memperbaiki fragmentasi internal / eksternal indeks seperti pada SQL Server?
- Ketika saya mengoptimalkan tabel di MySQL, apakah itu benar-benar membangun kembali semua indeks di atas meja?
- Apakah realistis untuk berpikir bahwa mengurangi ruang fisik indeks (tanpa membangun kembali pohon itu sendiri) benar-benar diterjemahkan menjadi kinerja yang lebih baik?
sumber
Jawaban:
Indeks fragmentasi terlalu berlebihan. Jangan khawatir tentang hal itu.
Dua blok yang berdekatan, agak kosong, digabung bersama oleh InnoDB sebagai pemrosesan alami.
Tindakan acak pada BTree menyebabkannya tertarik secara alami ke rata-rata 69% penuh. Tentu, ini bukan 100%, tetapi biaya overhead "memperbaiki" tidak sepadan.
SHOW TABLE STATUS
memberi Anda beberapa metrik, tetapi cacat - "Data_free" mencakup ruang "bebas" tertentu, tetapi bukan ruang "bebas" lainnya.Ada ruang yang tidak digunakan di setiap blok; blok 16KB gratis; "luasan" gratis (potongan nMB); Baris MVCC menunggu untuk dituai; node non-daun memiliki fragmentasi sendiri; dll.
Percona dan Oracle memiliki cara berbeda dalam melihat seberapa besar (jumlah blok) indeks. Saya menemukan keduanya tidak berguna karena definisi terbatas "bebas". Tampaknya blok (masing-masing 16KB) dialokasikan dalam potongan (beberapa MB), sehingga membuat orang percaya bahwa ada segala macam fragmentasi. Pada kenyataannya, biasanya hanya sebagian besar dari potongan multi-MB ini. Dan
OPTIMIZE TABLE
tidak perlu menutup ruang.Jika SQL Server menggunakan BTrees, maka berbohong untuk mengatakan bahwa "tidak ada fragmentasi". Pikirkan apa yang terjadi pada "block split". Atau pikirkan overhead defragmenting yang terus menerus. Bagaimanapun Anda kalah.
Perhatikan lebih lanjut bahwa tabel dan indeks pada dasarnya adalah struktur yang identik:
Jika sudah
innodb_file_per_table = ON
, Anda dapat dengan jelas melihat penyusutan (jika ada) setelah OPTIMASI TABEL dengan melihat.ibd
ukuran file. SebabOFF
, info dimakamkanibdata1
, tetapiSHOW TABLE STATUS
mungkin cukup akurat karena semua "bebas" ruang milik setiap tabel. Nah, kecuali untuk potongan yang dialokasikan sebelumnya.Anda mungkin memperhatikan bahwa tabel file-per-tabel yang baru dioptimalkan memiliki tepat 4M, 5M, 6M, atau 7M dari Data_free. Sekali lagi, ini adalah pra-alokasi, dan kegagalan untuk memberi Anda detail menit.
Saya telah bekerja dengan InnoDB selama lebih dari satu dekade; Saya telah bekerja dengan ribuan meja yang berbeda, besar dan kecil. Saya katakan bahwa hanya satu meja dalam seribu yang benar-benar dibutuhkan
OPTIMIZE TABLE
. Menggunakannya di meja lain adalah pemborosan.105 kolom banyak, tapi mungkin tidak terlalu banyak.
Apakah Anda memiliki 55 indeks pada satu tabel? Itu buruk. Itu adalah 55 pembaruan per
INSERT
. Mari kita bahas lebih lanjut. Ingatlah bahwaINDEX(a)
itu tidak berguna jika Anda juga memilikinyaINDEX(a,b)
. DanINDEX(flag)
tidak berguna karena kardinalitas rendah. (TapiINDEX(flag, foo)
semoga bermanfaat.)T1: Tidak ada cara yang baik untuk memeriksa semua bentuk fragmentasi baik dalam data atau indeks sekunder.
Q2, Q3:
OPTIMIZE TABLE
membangun kembali tabel denganCREATEing
tabel baru danINSERTing
semua baris, laluRENAMEing
danDROPping
. Memasukkan kembali data dalam urutan PK memastikan bahwa data didefragmentasi dengan baik. Indeks adalah masalah lain.T4: Anda dapat
DROP
danreCREATE
setiap indeks untuk membersihkannya. Tetapi ini adalah proses yang sangat lambat. 5.6 memiliki beberapa speedup, tetapi saya tidak tahu apakah mereka membantu defragmentasi.Hal ini juga memungkinkan untuk
ALTER TABLE ... DISABLE KEYS
, kemudianENABLE
mereka. Ini mungkin untuk membangun kembali semua indeks sekunder secara lebih efisien sekaligus.sumber
Lulus.
Itu benar-benar membangun kembali tabel dan indeksnya.
Itu pertanyaan yang sama dengan jawaban yang sama.
Tidak realistis untuk berpikir Anda dapat mengurangi ruang tanpa membangun kembali pohon. Mereka pergi bersama.
sumber
SHOW TABLE STATUS LIKE 'mytable'
akan memberikan petunjuk didata free
kolom. dev.mysql.com/doc/refman/5.6/id/show-table-status.html