Apakah overhead dari seringnya permintaan cache tidak valid?


22

Saat ini saya sedang mengerjakan database MySQL tempat kami melihat sejumlah besar pembatalan dari cache permintaan, terutama karena tingginya jumlah pernyataan INSERT, DELETE dan UPDATE yang dieksekusi di banyak tabel.

Apa yang saya coba untuk menentukan adalah apakah ada atau tidak ada manfaat sama sekali untuk memungkinkan cache query digunakan untuk pernyataan SELECT yang sedang dijalankan terhadap tabel-tabel ini. Karena mereka batal begitu cepat, menurut saya hal terbaik adalah menggunakan SQL_NO_CACHE pada pernyataan SELECT dengan tabel-tabel ini.

Apakah overhead dari seringnya invalidation sepadan?

Sunting: Atas permintaan pengguna @Rando_MySQLDBA di bawah ini, inilah info tentang MyISAM dan INNODB.

InnoDB

  • Ukuran Data: 177,414 GB
  • Ukuran Indeks: 114.792 GB
  • Ukuran Meja: 292.205 GB

MyISAM

  • Ukuran Data: 379.762 GB
  • Ukuran Indeks: 80.681 GB
  • Ukuran Meja: 460.443 GB

Informasi tambahan:

  • Versi: 5.0.85
  • query_cache_limit: 1048576
  • query_cache_min_res_unit: 4096
  • kueri_cache_size: 104857600
  • query_cache_type: ON
  • query_cache_wlock_invalidate: OFF
  • innodb_buffer_pool_size: 8841592832
  • RAM 24GB

2
dom.as/tech/query-cache-tuner merangkumnya dengan cukup baik
Laurynas Biveinis

Hehe, sangat berwawasan luas.
Craig Sefton

Jawaban:


16

Anda harus menonaktifkan cache permintaan dengan

[mysqld]
query_cache_size = 0

dan kemudian restart mysql. Mengapa saya menyarankan itu ???

Cache Kueri akan selalu berbenturan dengan InnoDB. Alangkah baiknya jika MVCC InnoDB akan membiarkan kueri dilayani dari cache kueri jika modifikasi tidak memengaruhi pembacaan berulang untuk transaksi lainnya. Sayangnya, InnoDB tidak melakukan itu. Rupanya, Anda memiliki banyak pertanyaan yang dibatalkan agak cepat dan mungkin tidak digunakan kembali.

Untuk InnoDB di bawah MySQL 4.0, cache kueri dinonaktifkan untuk transaksi. Untuk MySQL 4.1+, InnoDB memainkan polisi lalu lintas ketika mengizinkan akses ke cache kueri berdasarkan tabel.

Dari sudut pandang pertanyaan Anda, saya akan mengatakan bahwa pembenaran untuk menghapus cache kueri tidak terlalu mahal, tetapi bagaimana InnoDB mengelolanya.

Untuk informasi lebih lanjut tentang bagaimana InnoDB berinteraksi dengan cache kueri, silakan baca halaman 213-215 dari buku "MySQL Kinerja Tinggi (Edisi Kedua)" .

Jika semua atau sebagian besar data Anda adalah MyISAM, Anda bisa menggunakan ide awal Anda menggunakan SQL_NO_CACHE.

Jika Anda memiliki campuran InnoDB dan MyISAM, Anda harus menemukan keseimbangan yang tepat untuk aplikasi Anda berdasarkan pada seberapa tinggi kesalahan cache Anda. Bahkan, halaman 209-210 dari buku yang sama menunjukkan alasan untuk melewatkan cache:

  • Kueri ini tidak dapat di-cache, baik karena mengandung konstruk nondeterministik (seperti CURRENT_DATE) atau karena set hasilnya terlalu besar untuk disimpan. Kedua jenis kueri yang tidak dapat disimpan menambah variabel status Qcache_not_cached.
  • Server belum pernah melihat kueri sebelumnya, sehingga tidak pernah memiliki kesempatan untuk men-cache hasilnya.
  • Hasil kueri sebelumnya di-cache, tetapi server menghapusnya. Ini dapat terjadi karena tidak ada cukup memori untuk menyimpannya, karena seseorang menginstruksikan server untuk menghapusnya, atau karena itu tidak valid

dan akar penyebab kesalahan cache tinggi dengan beberapa kueri yang tidak bisa disimpan adalah:

  • Cache permintaan belum hangat. Itu adalah server tidak memiliki kesempatan untuk mengisi cache dengan set hasil.
  • Server melihat kueri yang belum pernah dilihat sebelumnya. Jika Anda tidak memiliki banyak kueri berulang, ini bisa terjadi bahkan setelah cache dipanaskan.
  • Ada banyak cacat cache.

UPDATE 2012-09-06 10:10 EDT

Melihat info terbaru Anda, Anda telah query_cache_limitmengatur ke 1048576 (1M). Ini membatasi hasil apa pun yang ditetapkan ke 1 jt. Jika Anda mengambil sesuatu yang lebih besar, itu tidak akan di-cache. Meskipun Anda telah query_cache_sizemenetapkan untuk 104857600 (100M), ini hanya memungkinkan untuk 100 hasil yang di-cache ditetapkan di dunia yang sempurna. Jika Anda melakukan ratusan pertanyaan, fragmentasi akan terjadi lebih cepat. Anda juga memiliki 4096 (4K) sebagai hasil ukuran minimum yang ditetapkan. Sayangnya, mysql tidak memiliki mekanisme internal untuk defragmenting cache permintaan.

Jika Anda harus memiliki cache kueri dan Anda memiliki begitu banyak RAM, Anda dapat menjalankan yang berikut:

SET GLOBAL query_cache_size = 0;
SELECT SLEEP(60);
SET GLOBAL query_cache_size = 1024 * 1024 * 1024;

untuk membersihkan cache kueri. Anda kehilangan semua hasil dalam tembolok, jadi jalankan baris ini selama jam sibuk.

Saya juga akan menetapkan yang berikut:

  • query_cache_size = 1G
  • query_cache_limit = 8M

Itu menyisakan 23G RAM. Saya akan mengajukan yang berikut:

  • innodb_buffer_pool_size = 12G
  • key_buffer_size = 4G

Itu menyisakan 7G. Ini harus memadai untuk Koneksi OS dan DB.

Perlu diingat bahwa buffer kunci hanya menyimpan cache halaman indeks MyISAM, sedangkan Pool Penyangga InnoDB menyimpan data dan indeks.

Satu rekomendasi lagi: tingkatkan ke MySQL 5.5 sehingga Anda dapat mengonfigurasi InnoDB untuk banyak CPU dan beberapa utas untuk baca / tulis I / O.

Lihat posting saya sebelumnya tentang penggunaan MySQL 5.5 bersamaan dengan mengakses beberapa CPU untuk InnoDB

UPDATE 2012-09-06 14:56 EDT

Metode saya untuk membersihkan cache permintaan agak ekstrem karena menyemprotkan data yang di-cache dan membentuk segmen RAM yang sama sekali berbeda. Seperti yang Anda tunjukkan dalam komentar Anda, FLUSH QUERY CACHE(seperti yang Anda sarankan) atau bahkan RESET QUERY CACHEakan lebih baik. Untuk klarifikasi, ketika saya mengatakan "tidak ada mekanisme internal," saya maksudkan itu. Defragmentasi diperlukan dan harus dilakukan secara manual. Itu harus crontab'd .

Jika Anda melakukan DML (INSERT, UPDATE, DELETEs) di InnoDB lebih sering daripada di MyISAM, saya akan mengatakan hapus cache permintaan sama sekali, yang saya katakan di awal.


Terima kasih atas tanggapannya. Saya memiliki buku itu dan telah menggunakannya secara luas; Saya mengetahui dengan baik alasan Anda menjabarkan kehilangan cache, tetapi seperti yang saya sebutkan, kami telah mengidentifikasi pembatalan cache sebagai masalah utama karena korelasi kuat yang kami lihat antara Com_select dan Qcache_inserts. Oh, dan DB yang dimaksud memiliki campuran INNODB dan MyISAM.
Craig Sefton

Diperbarui dengan info tambahan yang Anda minta. Terima kasih.
Craig Sefton

Terima kasih atas tanggapannya, saya menantikan sisanya. Salah satu hal yang kami identifikasi adalah bahwa sekitar 18% pertanyaan tidak di-cache, jadi sangat menghargai saran mengenai pengaturan. Sayangnya kotak ini tidak didedikasikan, tetapi rekomendasi Anda akan membantu. Fragmentasi jelas merupakan masalah juga. Saya masih benar-benar khawatir tentang jumlah pembatalan yang kami lihat (sebagai lawan dari pertanyaan yang tidak di-cache sama sekali), jadi masih tidak pasti apakah biaya overhead di sana layak atau tidak. Sangat menghargai wawasan Anda, terima kasih banyak.
Craig Sefton

Mengenai komentar Anda tentang "mysql tidak memiliki mekanisme internal untuk men-defrag cache permintaan", tidak bisakah Anda menjalankan perintah FLUSH QUERY CACHEuntuk men-defrag itu? Lihat: dev.mysql.com/doc/refman/5.0/en/flush.html
Craig Sefton

Diperbarui jawabanku ...
RolandoMySQLDBA

3

BAD: query_cache_size = 1G

Mengapa? Karena berapa lama siram akan memakan waktu. Artinya, ketika beberapa penulisan terjadi, seluruh 1GB akan dipindai untuk menemukan referensi ke tabel yang telah dimodifikasi. Semakin besar QC, semakin lambat ini. Saya merekomendasikan ukuran tidak lebih dari 50 juta, kecuali data Anda jarang berubah.

QC adalah overhead untuk MyISAM dan InnoDB. Itu mengeluarkan Mutex global, dan mengeluarkannya terlalu cepat. Mutex ini adalah salah satu alasan mengapa MySQL tidak dapat menggunakan lebih dari 8 core secara efektif.

SQL_NO_CACHE tidak diketahui sampai setelah Mutex dikunci! Tentang satu-satunya penggunaan untuk bendera itu adalah untuk pembandingan.

Seringkali lebih baik untuk memberikan RAM ke beberapa cache lainnya.


2

Saya dapat memikirkan kasus yang sempurna untuk itu, dan kami telah menguji secara menyeluruh dan menjalankannya dalam produksi ... Saya menyebutnya strategi pengelompokan "jalur cepat" :

Jika Anda melakukan pemisahan baca-tulis dengan proxy seperti MaxScale, atau aplikasi Anda mampu, Anda dapat mengirim beberapa bacaan untuk tabel-tabel yang jarang batal hanya untuk budak yang memiliki cache kueri dihidupkan, dan sisanya untuk budak lain dengan itu matikan.

Kami melakukan ini dan menangani panggilan 4M per menit ke cluster selama tes beban kami (bukan patokan ... kesepakatan sebenarnya) sebagai hasilnya. Aplikasi tidak menunggu pada master_pos_wait () untuk beberapa hal, sehingga terhambat oleh ulangan replikasi, dan meskipun kami telah melihatnya dengan status menunggu pembatalan Qcache pada throughput yang sangat tinggi, level throughput tersebut lebih tinggi daripada klaster bahkan mampu tanpa Qcache.

Ini berfungsi karena jarang ada yang relevan dalam cache kueri kecil pada mesin-mesin itu untuk tidak valid (kueri itu hanya relevan dengan tabel yang jarang diperbarui). Kotak-kotak ini adalah "jalur cepat" kami. Untuk sisa kueri yang dilakukan aplikasi, mereka tidak harus bersaing dengan Qcache karena mereka pergi ke kotak tanpa dihidupkan.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.