MySQL Lambat Menulis

8

Menyisipkan ke tabel berikut ini membutuhkan waktu hingga 70 detik untuk menyelesaikan:

CREATE TABLE IF NOT EXISTS `productsCategories` (
  `categoriesId` int(11) NOT NULL,
  `productsId` int(11) NOT NULL,
  PRIMARY KEY (`categoriesId`,`productsId`),
  KEY `categoriesId` (`categoriesId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Ada sekitar 100.000 baris dalam tabel, dan itu mengambil 7MB pada disk.

Apakah ada beberapa pengaturan di MySQL yang dapat meningkatkan kinerja penulisan?

my.cnfFile saya adalah sebagai berikut:

log-slow-queries="/var/log/mysql/slow-query.log"
long_query_time=1 
log-queries-not-using-indexes

innodb_buffer_pool_size=4G
innodb_log_buffer_size=4M
innodb_flush_log_at_trx_commit=2
innodb_thread_concurrency=8
innodb_flush_method=O_DIRECT

query_cache_size = 6G
key_buffer_size = 284M
query_cache_limit = 1024M
thread_cache_size = 128
table_cache = 12800

sort_buffer_size=2M
read_rnd_buffer_size = 8M
myisam_sort_buffer_size = 64M

read_buffer_size=128K

open_files_limit               = 1000
table_definition_cache         = 1024
table_open_cache               = 6000

max_heap_table_size=512M
tmp_table_size=4096M

max_connections=1000

thread_concurrency = 24

Berikut ini adalah pengaturan perangkat keras:

  • Dell R710
  • RAID10
  • RAM 48G

Mengingat perangkat keras ini, saya tidak akan mengharapkan masalah menjadi hambatan perangkat keras.

Ronn0
sumber
Bisakah Anda memberikan beberapa data objektif? Log, metodologi dan hasil pengujian / benchmarking Anda, hal semacam itu?
womble
Jenis log apa yang ingin Anda lihat? Satu-satunya hal yang saya lihat mengapa butuh waktu begitu lama adalah di de mtop . Saya akan menguji hal-hal seperti mengubah tabel ke tabel myisam, batas memori lebih tinggi, utas lebih tinggi.
Ronn0
Pengaturan terbaik untuk meningkatkan mysql ... adalah beralih ke postgres lol
Antony Gibbs
thread_concurrency = 24 tidak berpengaruh ... Anda dapat membuang garis itu
Antony Gibbs

Jawaban:

16

PENGAMATAN # 1

Hal pertama yang menarik perhatian saya adalah struktur meja

CREATE TABLE IF NOT EXISTS `productsCategories` (
  `categoriesId` int(11) NOT NULL,
  `productsId` int(11) NOT NULL,
  PRIMARY KEY (`categoriesId`,`productsId`),
  KEY `categoriesId` (`categoriesId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Harap perhatikan bahwa categoriesIdindeks dan KUNCI UTAMA dimulai dengan kolom yang sama. Ini adalah indeks yang berlebihan. Karena tabel ini adalah InnoDB, categoriesIdindeksnya berlebihan karena alasan lain: Semua indeks sekunder berisi kunci ke gen_clust_index (alias Clustered Index; Lihat apa yang digunakan gen_clust_index di mysql? )

Jika Anda menghapus categoriesIdindeks dengan

ALTER TABLE productsCategories DROP INDEX categoriesId;

ini akan meningkatkan INSERT secara dramatis karena tidak harus melakukan pemeliharaan indeks Sekunder dan Klaster tambahan.

PENGAMATAN # 2

Jika Anda melakukan operasi penyisipan massal, Anda memerlukan buffer penyisipan massal yang besar .

Silakan lihat posting saya yang lalu tentang ini:

PENGAMATAN # 3

Ukuran file log Anda terlalu kecil !!! Itu harus 25% dari Pool Buffer InnoDB, yang dalam kasus Anda harus 1G. Lihat posting saya tentang cara mengubah ukuran File Log InnoDB .

PENGAMATAN # 4

Tolong, jangan atur innodb_thread_concurrency !!! Saya belajar langsung di Percona Live NYC untuk meninggalkan pengaturan itu sendirian . Ini dinonaktifkan secara default di MySQL 5.5, Plugin MySQL 5.1 InnoDB, dan Percona Server 5.1+.

PENGAMATAN # 5

Anda perlu menggunakan innodb_file_per_table. Jika ini dinonaktifkan, saya membuat pemeliharaan file pada ibdata1 mimpi buruk. Baca posting saya tentang cara membersihkan InnoDB untuk menerapkan ini .

PENGAMATAN # 6

Jika Anda menggunakan MySQL 5.5 atau Percona Server, Anda harus mengatur opsi tertentu untuk membuat InnoDB menggunakan mutiple CPUs / multiple core. Silakan lihat posting saya di pengaturan itu .

PENGAMATAN # 7

Kamu punya innodb_log_buffer_size=4M. Standarnya adalah 8M. Itu akan menyebabkan pembilasan dua kali lebih banyak ke redo log. Itu juga akan menangkal innodb_flush_log_at_trx_commit=2pengaturan Anda . Harap setel ke 32M. Juga, silakan lihat Dokumentasi MySQL di innodb_log_buffer_size .

Sehubungan dengan pengamatan ini, silakan tambahkan atau ganti pengaturan berikut:

[mysqld]
innodb_thread_concurrency = 0
innodb_read_io_threads = 64
innodb_write_io_threads = 64
innodb_io_capacity = 5000
innodb_file_per_table
innodb_log_file_size=1G
innodb_log_buffer_size=1G
bulk_insert_buffer_size = 256M
RolandoMySQLDBA
sumber
Wow terima kasih! Saya mencetak semua poin dan mengerjakannya sekarang dan menyimpannya di otak untuk membantu orang lain di masa depan. Terimakasih banyak!
Ronn0
2
query_cache_sizesangat besar juga. Setiap sisipan akan membutuhkan cache hingga 6GB untuk bisa dihapus.
Aaron Brown
@AaronBrown saya setuju. Saya membaca di buku MySQL Kinerja Tinggi bahwa InnoDB melakukan hal-hal yang membosankan dengan ID transaksi pada tabel InnoDB dalam cache permintaan yang membuatnya agak tidak perlu, belum lagi lambat, untuk menggunakan cache permintaan. Bahkan, MySQL 4.1 memiliki cache permintaan dinonaktifkan untuk InnoDB.
RolandoMySQLDBA
Saya pikir cache permintaan benar-benar terpisah dari mesin penyimpanan. Ini pada dasarnya membuat serial semua operasi penulisan dengan memaksa segalanya untuk pergi dan memindai cache kueri agar kueri tidak valid. Saya tidak pernah menemukan kasus penggunaan untuk itu dan selalu menyebabkan masalah.
Aaron Brown
satu hal lagi untuk ditambahkan: query_cache_size = 6G <- ini benar-benar dan sangat tidak masuk akal. Tembolok kueri seringkali lebih baik dinonaktifkan, dan pastinya tidak boleh lebih lambat dari 32M atau 64M. Overhead dari mempertahankan cache permintaan 6G tentu saja merugikan kinerja.
Gavin Towey
0

Anda harus memeriksa innodb_log_file_size, pengaturan default adalah 5M yang cukup rendah untuk pengaturan menulis intensif. Pertimbangkan untuk mengaturnya ke 100 juta. Anda harus menghapus ib_logfile*file lama untuk memulai DB dengan pengaturan baru. Tolong jangan menghapus file log saat server DB sedang berjalan, Anda harus menghentikannya terlebih dahulu. Mungkin Anda harus membuat cadangan file log lama terlebih dahulu, bukan hanya menghapusnya.

Alex
sumber