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

Kinerja MySQL:beberapa tabel vs. indeks pada satu tabel dan partisi

Membuat 20.000 tabel adalah ide yang buruk. Anda akan membutuhkan 40.000 tabel sebelum lama, dan kemudian lebih banyak lagi.

Saya menyebut sindrom ini Metadata Tribbles dalam buku saya SQL Antipatterns . Anda melihat ini terjadi setiap kali Anda berencana membuat "tabel per X" atau "kolom per X".

Ini memang menyebabkan masalah kinerja nyata ketika Anda memiliki puluhan ribu tabel. Setiap tabel memerlukan MySQL untuk memelihara struktur data internal, deskriptor file, kamus data, dll.

Ada juga konsekuensi operasional praktis. Apakah Anda benar-benar ingin membuat sistem yang mengharuskan Anda membuat tabel baru setiap kali pengguna baru mendaftar?

Sebagai gantinya, saya sarankan Anda menggunakan Partisi MySQL .

Berikut ini contoh mempartisi tabel:

CREATE TABLE statistics (
  id INT AUTO_INCREMENT NOT NULL,
  user_id INT NOT NULL,
  PRIMARY KEY (id, user_id)
) PARTITION BY HASH(user_id) PARTITIONS 101;

Ini memberi Anda keuntungan dalam mendefinisikan satu tabel logis, sekaligus membagi tabel menjadi banyak tabel fisik untuk akses yang lebih cepat saat Anda melakukan kueri untuk nilai tertentu dari kunci partisi.

Misalnya, Saat Anda menjalankan kueri seperti contoh Anda, MySQL hanya mengakses partisi yang benar yang berisi user_id tertentu:

mysql> EXPLAIN PARTITIONS SELECT * FROM statistics WHERE user_id = 1\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: statistics
   partitions: p1    <--- this shows it touches only one partition 
         type: index
possible_keys: NULL
          key: PRIMARY
      key_len: 8
          ref: NULL
         rows: 2
        Extra: Using where; Using index

Metode partisi HASH berarti bahwa baris ditempatkan di partisi dengan modulus kunci partisi integer. Ini berarti bahwa banyak user_id dipetakan ke partisi yang sama, tetapi setiap partisi rata-rata hanya memiliki 1/N baris (di mana N adalah jumlah partisi). Dan Anda mendefinisikan tabel dengan jumlah partisi yang konstan, sehingga Anda tidak perlu memperluasnya setiap kali Anda mendapatkan pengguna baru.

Anda dapat memilih berapa pun jumlah partisi hingga 1024 (atau 8192 di MySQL 5.6), tetapi beberapa orang telah melaporkan masalah kinerja ketika mereka mencapai tingkat itu.

Disarankan untuk menggunakan bilangan prima dari partisi. Jika nilai user_id Anda mengikuti suatu pola (seperti hanya menggunakan angka genap), menggunakan partisi bilangan prima membantu mendistribusikan data secara lebih merata.

Kembalikan pertanyaan Anda di komentar:

Untuk partisi HASH, jika Anda menggunakan 101 partisi seperti yang saya tunjukkan pada contoh di atas, maka setiap partisi yang diberikan rata-rata memiliki sekitar 1% dari baris Anda. Anda mengatakan tabel statistik Anda memiliki 30 juta baris, jadi jika Anda menggunakan partisi ini, Anda hanya akan memiliki 300 ribu baris per partisi. Itu jauh lebih mudah bagi MySQL untuk dibaca. Anda dapat (dan harus) menggunakan indeks juga -- setiap partisi akan memiliki indeksnya sendiri, dan ukurannya hanya 1% dari indeks pada seluruh tabel yang tidak dipartisi.

Jadi jawaban bagaimana Anda bisa menentukan jumlah partisi yang masuk akal adalah:seberapa besar seluruh tabel Anda, dan seberapa besar rata-rata partisi yang Anda inginkan?

Jumlah partisi tidak perlu bertambah jika Anda menggunakan partisi HASH. Akhirnya Anda mungkin memiliki total 30 miliar baris, tetapi saya telah menemukan bahwa ketika volume data Anda bertambah besar, itu tetap menuntut arsitektur baru. Jika data Anda tumbuh sebesar itu, Anda mungkin memerlukan sharding melalui beberapa server serta mempartisi menjadi beberapa tabel.

Karena itu, Anda dapat mempartisi ulang tabel dengan ALTER TABLE:

ALTER TABLE statistics PARTITION BY HASH(user_id) PARTITIONS 401;

Ini harus merestrukturisasi tabel (seperti kebanyakan perubahan ALTER TABLE), jadi diperkirakan akan memakan waktu cukup lama.

Anda mungkin ingin memantau ukuran data dan indeks dalam partisi:

SELECT table_schema, table_name, table_rows, data_length, index_length
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE partition_method IS NOT NULL;

Seperti halnya tabel apa pun, Anda ingin ukuran total indeks aktif agar sesuai dengan kumpulan buffer Anda, karena jika MySQL harus menukar bagian indeks masuk dan keluar dari kumpulan buffer selama kueri SELECT, kinerja akan menurun.

Jika Anda menggunakan partisi RANGE atau LIST, maka menambahkan, menjatuhkan, menggabungkan, dan memisahkan partisi jauh lebih umum. Lihat http://dev.mysql. com/doc/refman/5.6/en/partitioning-management-range-list.html

Saya mendorong Anda untuk membaca bagian manual tentang partisi , dan juga lihat presentasi yang bagus ini:Tingkatkan Kinerja Dengan Partisi MySQL 5.1 .



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. kolom stempel waktu mysql

  2. MySQL Trigger - Menyimpan SELECT dalam variabel

  3. Simpan dan ulangi hasil kueri di mysqli

  4. Menulis bahasa Ibrani ke mySql menggunakan JAVA

  5. Mysql mengubah mesin tabel MyISAM ke InnoDB