Haruskah saya menggunakan Transient API untuk menyimpan HTML String, atau Object?

18

Mari kita asumsikan ada plugin yang menampilkan 20 posting terkait (untuk setiap posting) dengan kueri yang sangat kompleks. Dan kemudian menggunakan data dari kueri ini, ia membangun tata letak HTML yang kompleks. Juga, harus dicatat bahwa plugin bersifat publik, dan dapat diinstal pada server apa pun dengan konfigurasi apa pun.

Sesuatu seperti:

/* complex and large query */
$related_posts = get_posts( ... );

$html_output = '';
foreach($related_posts as $key => $item) {
     /* complex layout rendering logic (but not as slow as the previous query) */   
     $html_output .= ...;
}

Jadi pertanyaan saya adalah:

  • Apa cara teraman dan paling benar untuk menyimpan data seperti itu?
  • Haruskah saya menggunakan Transient API ke cache $related_postsarray, atau $html_outputstring? Jika saya akan menyimpan $html_ouputstring, apakah akan mencapai batas ukuran maksimal? Haruskah saya gzip, sebelum menyimpan?
  • Haruskah saya menggunakan API sementara di sini?
Marvin3
sumber

Jawaban:

18

Haruskah saya menggunakan API sementara di sini?

Tidak.

Dalam stok, WordPress, transien instalasi disimpan di tabel wp_options, dan hanya dibersihkan selama peningkatan inti. Misalkan Anda memiliki 50.000 posting, itu 50.000 baris tambahan dalam tabel opsi. Jelas mereka diatur untuk memuat otomatis = tidak, jadi itu tidak akan menghabiskan semua memori Anda, tetapi ada peringatan lain.

Bidang isian otomatis dalam tabel opsi tidak memiliki indeks, yang berarti bahwa panggilan ke wp_load_alloptions()akan melakukan pemindaian tabel penuh. Semakin banyak baris yang Anda miliki, semakin lama waktu yang dibutuhkan. Semakin sering Anda menulis ke tabel opsi, cache internal MySQL kurang efisien.

Jika data yang di-cache terkait langsung dengan sebuah posting, Anda sebaiknya menyimpannya dalam postingan meta. Ini juga akan menyelamatkan Anda kueri setiap kali Anda perlu menampilkan konten yang di-cache, karena cache meta post (biasanya) disiapkan selama pencarian posting di WP_Query.

Struktur data Anda untuk nilai meta dapat bervariasi, Anda dapat memiliki stempel waktu dan melakukan kueri mahal Anda jika nilai yang di-cache sudah usang, mirip dengan perilaku sementara.

Satu pemikiran penting lain yang perlu diingat adalah transien WordPress dapat berubah-ubah di lingkungan dengan caching objek yang persisten. Ini berarti bahwa jika Anda menyimpan data cache Anda selama 24 jam dalam sementara, sama sekali tidak ada jaminan itu akan tersedia dalam 23 jam, atau 12, atau bahkan 5 menit. Backend cache objek untuk banyak pemasangan adalah penyimpanan nilai kunci dalam memori seperti Redis atau Memcached, dan jika tidak ada cukup memori yang dialokasikan agar sesuai dengan objek yang lebih baru, item yang lebih lama akan diusir. Ini adalah kemenangan besar untuk pendekatan penyimpanan meta.

Validasi juga bisa lebih pintar, yaitu mengapa Anda membatalkan cache posting terkait dalam X jam? Apakah karena beberapa konten telah berubah? Pos baru telah ditambahkan? Tag baru telah ditetapkan? Bergantung pada "kueri kompleks dan besar" Anda, Anda dapat memilih untuk membatalkan HANYA jika terjadi sesuatu yang akan mengubah hasil kueri Anda.

Haruskah saya menggunakan Transient API ke cache $ related_posts array, atau $ html_output string? Jika saya akan men-cache $ html_ouput string, apakah akan mencapai batas ukuran maksimal? Haruskah saya gzip, sebelum menyimpan?

Tergantung pada ukuran string Anda, karena itulah data yang akan mengalir antara PHP, MySQL, dll. Anda harus berusaha sangat keras untuk mencapai batas MySQL, tetapi misalnya Memcached default per-object limit adalah hanya 1 mb.

Berapa lama "logika rendering tata letak kompleks" Anda sebenarnya diperlukan? Jalankan melalui profiler untuk mengetahuinya. Kemungkinannya sangat cepat tidak akan pernah menjadi hambatan.

Jika itu masalahnya, saya akan menyarankan caching ID posting. Bukan objek WP_Post, karena itu akan berisi konten posting lengkap, tetapi hanya array ID posting. Kemudian gunakan a WP_Querydengan post__inyang akan menghasilkan permintaan MySQL yang sangat cepat dengan kunci primer.

Yang mengatakan, jika data yang dibutuhkan per item cukup sederhana, mungkin judul, url thumbnail dan permalink, maka Anda dapat menyimpan hanya tiga, tanpa overhead dari perjalanan pulang-pergi tambahan ke MySQL, dan tanpa overhead caching HTML yang sangat panjang string.

Wow itu banyak kata-kata, semoga bisa membantu

kovshenin
sumber
12

Tidak Semua Kode WP Adalah Kode Publik

Jika Anda akan merilis sesuatu untuk umum, maka semua hal yang dikatakan kovshenin benar-benar valid.

Hal-hal berbeda jika Anda akan menulis kode pribadi untuk diri sendiri atau perusahaan Anda.

Cache Objek Eksternal Adalah Manfaat Besar, Bagaimanapun

Untuk mengatur cache objek persisten eksternal sangat dianjurkan , bila Anda bisa.

Semua hal yang dikatakan dalam jawaban kovshenin tentang transien dan MySQL sangat benar, dan mengingat WP itu sendiri dan sekelompok plugin menggunakan cache objek ... maka peningkatan kinerja yang Anda dapatkan, sangat sepadan dengan usaha (kecil) untuk menyiapkan sistem cache modern seperti Redis atau Memcached.

Nilai-Nilai Cached Mungkin Tidak Ada Di Sana: Tidak masalah

Selain itu, ya, cache objek eksternal tidak dapat diandalkan. Anda seharusnya tidak pernah mengandalkan fakta bahwa transien ada di sana. Anda perlu memastikan itu berfungsi jika cache tidak berada di tempat seharusnya .

Cache bukan penyimpanan, cache adalah cache.

Gunakan Cache Secara Selektif

Lihat contoh ini:

function my_get_some_value($key) {
   // by default no cache when debug and if no external object_cache
   $defUse = ! (defined('WP_DEBUG') && WP_DEBUG) && wp_using_ext_object_cache();
   // make the usage of cache filterable
   $useCache = apply_filters('my_use_cache', $defUse);
   // return cached value if any
   if ($useCache && ($cached = get_transient($key))) {
     return $cached;
   }
   // no cached value, make sure your code works with no cache
   $value = my_get_some_value_in_some_expensive_way();
   // set cache, if allowed
   $useCache and set_transient($key, $value, HOUR_IN_SECONDS);

   return $value;
}

Menggunakan kode seperti ini, di situs pribadi Anda, kinerja situs dapat meningkat banyak , terutama jika Anda memiliki banyak pengguna.

Perhatikan bahwa:

  • Secara default, cache tidak digunakan saat debug aktif, jadi semoga pada lingkungan pengembangan Anda. Percayalah, cache bisa membuat debug menjadi neraka
  • Secara default cache juga tidak digunakan ketika WP tidak diatur untuk menggunakan cache objek eksternal. Ini berarti bahwa semua masalah yang terhubung dengan MySQL tidak ada, karena Anda tidak menggunakan transient ketika mereka menggunakan MySQL. Alternatif yang mungkin lebih mudah adalah menggunakan wp_cache_*fungsi , jadi jika tidak ada cache eksternal yang diatur, maka cache terjadi dalam memori, dan database tidak pernah terlibat.
  • Penggunaan cache dapat difilter, untuk menangani beberapa kasus tepi yang mungkin Anda temui

Tidak Ada Skala Web Jika Tidak Ada Tembolok

Anda seharusnya tidak mencoba memecahkan masalah kecepatan dengan cache. Jika Anda memiliki masalah kecepatan, maka Anda harus memikirkan kembali kode Anda.

Tetapi untuk skala situs web di webscale, cache sangat diperlukan .

Dan banyak kali (tetapi tidak selalu) fragmen, cache yang sadar konteks jauh lebih fleksibel dan cocok daripada caching fullpage yang agresif.

Pertanyaan Anda:

Haruskah saya menggunakan API sementara di sini?

Itu tergantung .

Apakah kode Anda menghabiskan banyak sumber daya? Jika tidak, mungkin tidak perlu cache. Seperti yang dikatakan, bukan hanya masalah kecepatan. Jika kode Anda berjalan cepat tetapi membutuhkan banyak CPU dan memori untuk beberapa pengguna ... apa yang terjadi ketika Anda memiliki 100 atau 1000 pengguna secara bersamaan?

Jika Anda menyadari cache akan menjadi ide yang bagus ..

... dan kode publik: mungkin tidak . Anda dapat mempertimbangkan untuk melakukan cache secara selektif, seperti dalam contoh saya di atas dalam kode publik, tetapi biasanya lebih baik jika Anda menyerahkan keputusan tersebut kepada pelaksana.

... dan merupakan kode pribadi: sangat mungkin ya . Tetapi bahkan untuk kode pribadi, melakukan cache secara selektif masih merupakan hal yang baik, misalnya untuk debug.

Ingatlah, wp_cache_*fungsi itu dapat memberi Anda akses ke cache tanpa risiko mencemari basis data.

Haruskah saya menggunakan Transient API ke cache $ related_posts array, atau $ html_output string?

Itu tergantung pada banyak hal. Seberapa besar talinya? Cache eksternal mana yang Anda gunakan? Jika Anda akan meng-cache posting, menyimpan ID sebagai array bisa menjadi ide yang baik, meminta jumlah posting yang layak dengan ID mereka cukup cepat.

Catatan Akhir

API sementara mungkin merupakan salah satu hal terbaik dari WordPress. Berkat plugin yang dapat Anda temukan untuk semua jenis sistem cache, itu menjadi API sederhana yang bodoh untuk sejumlah besar perangkat lunak yang dapat bekerja di bawah tenda.

Di luar WordPress, abstraksi semacam itu yang bekerja di luar kotak dengan sekelompok sistem caching yang berbeda, dan memungkinkan Anda untuk beralih dari satu sistem ke sistem lainnya tanpa upaya yang sangat sulit ditemukan.

Anda jarang dapat mendengar saya mengatakan bahwa WordPress lebih baik daripada hal-hal modern lainnya, tetapi API sementara adalah salah satu dari beberapa hal yang saya lewatkan ketika saya tidak bekerja dengan WordPress.

Tentunya cache itu sulit, tidak memecahkan masalah kode dan bukan peluru perak, tetapi sesuatu yang Anda butuhkan untuk membangun situs lalu lintas tinggi yang berfungsi.

Gagasan WordPress untuk menggunakan tabel MySQL yang dioptimalkan untuk melakukan cache cukup gila, tetapi tidak lebih baik untuk menjauhkan diri dari cache hanya karena WordPress, secara default, melakukannya.

Anda hanya perlu memahami cara kerja berbagai hal, lalu tentukan pilihan Anda.

gmazzap
sumber
2

Jawaban sebelumnya telah menyoroti kewajiban " Itu tergantung. ", Yang saya setujui sepenuhnya.

Saya ingin menambahkan rekomendasi, berdasarkan pada bagaimana saya " mengira " ini akan lebih baik dilakukan dalam skenario yang Anda gambarkan di atas.

Saya tidak akan menggunakan Transients dalam kasus itu, melainkan Post Meta , karena satu keuntungan yang dimiliki oleh yang terakhir: Kontrol .

Karena Anda perlu men-cache data berdasarkan per-posting, jumlah data yang akan Anda cache tergantung pada jumlah posting, dan akan bertambah seiring waktu. Setelah melampaui jumlah posting tertentu, Anda mungkin mencapai batas memori yang bisa digunakan oleh cache objek Anda, dan itu akan mulai menghapus data yang sebelumnya di-cache dari memori sebelum kedaluwarsa. Ini dapat mengarah pada situasi, di mana Anda memiliki gelombang pengunjung yang besar, di mana setiap pengunjung akan memicu "SQL yang terlalu rumit" pada setiap permintaan halaman, dan situs Anda akan sepenuhnya macet.

Jika Anda men-cache data di Post Meta Anda, Anda tidak hanya dapat mengontrol bagaimana data itu disimpan dan diambil, tetapi Anda juga dapat mengontrol bagaimana itu diperbarui. Anda akan menambahkan pekerjaan cron untuk ini yang berjalan hanya pada periode waktu di mana ada sedikit atau tidak ada lalu lintas ke situs. Jadi, "permintaan lambat" tidak pernah ditemui oleh pengguna situs yang sebenarnya, dan Anda bahkan dapat memuatnya terlebih dahulu, sehingga pekerjaannya sudah dilakukan ketika pengunjung pertama kali klik.

Perlu diingat bahwa semua caching adalah kompromi! Itu sebabnya jawaban yang biasa adalah "Itu tergantung." dan mengapa tidak ada "caching grail grail".

Alain Schlesser
sumber