Trick Handle Large Data with Gridview + Cache

downloadMelanjutkan status sebelumnya tentang large data (jutaan record) yang by default akan lemot jika kita menampilkannya menggunakan Gridview. Penyebabnya adalah Query ini..

SELECT COUNT(*) FROM nama_tabel

Gridview menggunakannnya untuk mengatur paging, dan menampilkan summary data.

Tepatnya ada disini https://github.com/yiisoft/yii2/blob/master/framework/data/ActiveDataProvider.php#L164, pada fungsi protected function prepareTotalCount(), berikut ini kodenya:

return (int) $query->limit(-1)->offset(-1)->orderBy([])->count('*', $this->db);

Kita bisa aja mengoveride kode tersebut dan menggantinya dengan yang menurut kita lebih baik n cepat, namun itu core dari Yii 2, agak tabu jika kita otak atik.. :)

Nah saya menemukan solusi yang lebih cantik, ternyata kita bisa mengoverride perhitungan total count via object ActiveDataProvider..

Pada Search Model action search(), kita akan dapati:

$dataProvider = new ActiveDataProvider([
	'query' => $query,
]);

Nah kita bisa menambahkan parameter totalCount

$dataProvider = new ActiveDataProvider([
	'query' => $query,
	'totalCount' => (int)$totalCount,
]);

Dengan cara ini Anda bisa membuat Query yang lebih cepat dibandingkan dengan count, itu terserah Anda..

Namun bagi nyubi yang gak tau harus gimana, saya berbaik hati memberikan bantuan sedikit, dalam hal ini saya menggunakan cache untuk menyimpan nilai totalCount sehingga pada load kedua bisa lebih cepat.

$query = Employee::find()->asArray();
$cache = Yii::$app->cache;	
$totalCount = $cache->get('countEmployee');
if ($totalCount === false) {
	$dependency = [
		'class' => 'yii\caching\DbDependency',
		'sql' => 'SELECT MAX(id) FROM employee',
	];
	$cache->set('countEmployee', $query->count(), 0, $dependency);
	$totalCount = $cache->get('countEmployee');
}      

$dataProvider = new ActiveDataProvider([
	'query' => $query,
	'totalCount' => (int)$totalCount,
]); 

Anda tidak harus menggunakan pendekatan $query->count() untuk menghitung total, Anda bisa menggunakan Query SELECT MAX(id) FROM employee mungkin.. yang pasti lebih cepat, atau mekanisme lain seperti Anda simpan di database total row dan Anda update otomatis ketika terjadi update data tabel via behaviour.. semua terserah gimana enaknya Anda

Nah, saya juga menggunakan dependency sehingga cache akan valid nilainya selama query di dependency menghasilkan data yang sama SELECT MAX(id) FROM employee, query dependency inipun juga fleksibel bisa Anda ganti.. tergantung tabel Anda, jika di tabel Anda ada field update_at (datetime) yang diupdate otomatis via behaviour maka Anda bisa gunakan sebagai dependency, misal SELECT MAX(update_at) FROM employee

Tutorial ini diujicoba di 2,5 Juta row record, dan berjalan memuaskan. :)
CMIIW

3 Comments
  1. greyoura
    • Hafid Mukhlasin
    • LieTsen

Leave a Reply

Your email address will not be published. Required fields are marked *