MySQL di WordPress Terlalu Besar, Ini Solusinya; Studi Kasus Website Berita (Bagian 1)

Sebelum Tulisan Dimulai…
Ada seorang klien saya yang menjalankan situs web berita (online dan cetak), media online tentu saja memakai CMS sejuta umat: WordPress :- D. Saat ini wartawan mereka dibilang sangat produktif. Dalam satu tahun, bisa sampai 25.000-35.000 posting (artinya 70-100 posting perhari, wuih).

Nah, media online ini dimulai dari tahun 2013, kalau kita ambil nilai terkecil, artinya 3 tahun x 25.000 = 75000 posting sudah.

Tentu ini menyebabkan masalah, setelah didepak dari shared-hosting, juga sudah dilakukan berpindah-pindah VPS. Untuk membeli Dedicated Server, sepertinya mereka belum sanggup.

Tulisan Sesudah Sebelum Tulisan Dimulai…
Solusinya sudah banyak dilakukan, salah satunya memakai plugin cache, bahkan yang berbayar. Memang plugin cache ini sangat membantu, sehingga tidak banyak terjadi kueri di MySQL.

Tapi yang jadi masalah adalah saat terjadi flush cache/clear cache, ini menyebabkan MySQL kerja terlalu tinggi.

Solusi selanjutnya? Yang paling terpikir dari saya adalah: dibanding memaksakan diri semua posting di dalam satu database, kenapa tidak dibagi-bagi? Jadi, menurut pendapat saya: Berita lama tentu jarang ada yang mengakses, kenapa tidak kita buat saja website khusus arsip lama?

Jadi, langkah yang saya terapkan:

  1. Buat subdomain, terserah namanya apa, dalam kasus ini saya buat tahun arsip saja. Jadi dibuatlah subdomain 2013.namadomainklien.com, lalu 2014.namadomainklien.com. Untuk yang tahun berjalan (2015), tidak perlu.
  2. Backup berkas dan database, lalu restore di subdomain tsb.
  3. Nah, di sini permainan database dimulai, hehe.. untuk yang arsip tahun 2013, saya mencoba menghapus semua posting yang tidak bertahun 2013. Jadi, di PhpMyAdmin saya tinggal masukkan query SQL:
    DELETE FROM `wp_posts` WHERE `post_date` >= "2014-01-01 00:00:00" AND `post_type`="post"

    query di atas akan menghapus semua row di tabel yang bertanggal lebih dari 31 Desember 2013, dan dengan tipe posting: `post` (ini penting, jangan sampai kamu juga menghapus posting dengan tipe `page` maupun attachment agar struktur di website tetap terjaga).

  4. Jika sudah, lakukan “pembersihan” di tabel `wp_term_relationships` juga `wp_postmeta` agar menghilangkan row yang tidak berguna. Berikut query sql nya:
    DELETE tr FROM wp_term_relationships tr
    INNER JOIN wp_term_taxonomy tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id)
    WHERE tt.taxonomy != 'link_category'
    AND tr.object_id NOT IN (SELECT ID FROM wp_posts);

    lalu query ini:

    SELECT * FROM wp_postmeta pm LEFT JOIN wp_posts wp ON wp.ID = pm.post_id WHERE wp.ID IS NULL;
    DELETE pm FROM wp_postmeta pm LEFT JOIN wp_posts wp ON wp.ID = pm.post_id WHERE wp.ID IS NULL;

     

  5. Jika sudah lakukan optimize table, ke struktur tabel di database, lalu cek saja semua tabel, lalu pilih optimize table.

    Optimize Table di PhpMyAdmin

    Optimize Table di PhpMyAdmin

  6. Jika sudah, jangan lupa untuk mengubah URL dari namadomainklien.com ke 2015.namadomainklien.com, cara paling mudah dan efektif menurut saya adalah mengubah berkas `wp-config.php` dan menambahkan:
    define('WP_HOME','http://2013.namadomainklien.com');
    define('WP_SITEURL','http://2013.namadomainklien.com');

    ubah URL website

    ubah URL website

  7. Jika sudah, maka ubah semua URL di baik di ini posting maupun di guid ke arah domain baru:
    UPDATE wp_posts SET post_content = REPLACE(post_content,'http://www.namadomainklien.com/wp-content/uploads/2013/','http://2013.namadomainklien.com/wp-content/uploads/2013/');
    
    UPDATE wp_posts SET guid = REPLACE(guid,'http://www.namadomainklien.com/wp-content/uploads/2013/','http://2013.namadomainklien.com/wp-content/uploads/2013/');

     

Tulisan Sesudah Tulisan…
Sekian dulu, lanjut di posting bagian 2, seting berkas `.htaccess` agar redirect ke website arsip. Lalu seting juga plugin cache agar tidak memberatkan MySQL kembali.

Update 14 November 2015: MySQL di WordPress Terlalu Besar, Ini Solusinya; Studi Kasus Website Berita (Bagian 2)