ثبت نام

کش کوئری MySQL بدون نیاز به تغییر در برنامه توسط mysqlnd_qc

مدیر ارشد و مؤسس سایت
آواتار کاربر
پست: 28
تشکر کرده: 16 پست
تشکر شده: 13 پست
تاریخ عضویت: 20 بهمن 91, 03:55
محل اقامت: اهواز

کش کوئری MySQL بدون نیاز به تغییر در برنامه توسط mysqlnd_qc

پستتوسط Nabi » 28 اردیبهشت 98, 01:36

شاید براتون پیش اومده که سایتی از قبل داشتید که با PHP و MySQL نوشتید و بعد ها تصمیم گرفتید کوئری های دیتابیس رو کش کنید اما وقتی به کدها برمیگردید چیزی یادتون نمیاد! یا حتی در سناریوی دیگه، پروژه ای دارید که نمیخواید یا نمیتونید یا دسترسی ندارید تغییراتی در اون بدید.
حتی اگر موارد فوق هم مطرح نباشند، بازهم اضافه کردن قابلت کش شدن کوئری های دیتابیس بدون اینکه یک خط در کدهای برنامه و کوئری هاتون تغییرات بدید به نظر جذاب میرسه.
البته برنامه و روش های خیلی زیادی برای مبحث کش دیتابیس وجود داره، اما روشی که میخوام در موردش صحبت کنم یکی از ساده ترین، بی دردسرترین و سر راست ترین روش هاست.

برای اینکار نیاز به درایور mysqlnd دارید که توسط PHP ارائه و از نسخه 5.4 به شکل پیشفرض روی اون نصب و فعال هست. بنابراین وارد موضوع نصب و فعالسازی اون نمیشیم.

اما چیزی که بهش نیاز دارید و باید نصب بشه، ماژول mysqlnd_qc هست که روی mysqlnd سوار میشه.

mysqlnd_qc یک کتابخانه PECL هست که با دستور زیر در خط فرمان به سادگی قابل نصبه:
کد: انتخاب همه
pecl install mysqlnd_qc


و یا به شکل دستی از اینجا قابل دانلود و نصب هست:
https://pecl.php.net/package/mysqlnd_qc

اون رو در شاخه ext از مسیر نصب PHP کپی و دستور زیر رو در php.ini بنویسید:
لینوکس:
کد: انتخاب همه
extension=php_mysqlnd_qc.so
ویندوز:
کد: انتخاب همه
extension=php_mysqlnd_qc.dll


این چند کوئری ساده هست برای نشون دادن قابلیت این ویژگی هست:
کد: انتخاب همه
<?php
/* Use constants for maximum portability */
$query = "/*" . MYSQLND_QC_ENABLE_SWITCH . "*/SELECT id FROM test";

/* Valid but less portable: default TTL */
$query = "/*qc=on*/SELECT id FROM test";

/* Valid but less portable: per statement TTL */
$query = "/*qc=on*//*qc_ttl=5*/SELECT id FROM test";

?>


و این یک نمونه کد دیگه برای مشاهده کارکرد این کش سیستم mysql هست:
کد: انتخاب همه
<?php
/* Connect, create and populate test table */
$mysqli = new mysqli("host", "user", "password", "schema", "port", "socket");
$mysqli->query("DROP TABLE IF EXISTS test");
$mysqli->query("CREATE TABLE test(id INT)");
$mysqli->query("INSERT INTO test(id) VALUES (1), (2)");

/* Will be cached because of the SQL hint */
$start = microtime(true);
$res   = $mysqli->query("/*" . MYSQLND_QC_ENABLE_SWITCH . "*/" . "SELECT id FROM test WHERE id = 1");

var_dump($res->fetch_assoc());
$res->free();

printf("Total time uncached query: %.6fs\n", microtime(true) - $start);

/* Cache hit */
$start = microtime(true);
$res   = $mysqli->query("/*" . MYSQLND_QC_ENABLE_SWITCH . "*/" . "SELECT id FROM test WHERE id = 1");

var_dump($res->fetch_assoc());
$res->free();

printf("Total time cached query: %.6fs\n", microtime(true) - $start);
?>

خروجی:
کد: انتخاب همه
array(1) {
  ["id"]=>
  string(1) "1"
}
Total time uncached query: 0.000740s
array(1) {
  ["id"]=>
  string(1) "1"
}
Total time cached query: 0.000098s


زمان اجرا رو میبینید که از 0.000740 ثانیه به 0.000098 ثانیه کاهش یافته.

به شکل خلاصه و کلیدی، برای اینکه یک کوئری کش بشه، ابتدای کوئری باید از یک کلمه کلیدی استفاده کنید بدین صورت:
کد: انتخاب همه
"/*qc=on*/SELECT id FROM test"

و یا بهتر از اون، پیشنهاد میشه اینطوری و از ثابت مخصوصش استفاده کنید:
کد: انتخاب همه
"/*" . MYSQLND_QC_ENABLE_SWITCH . "*/" . "SELECT id FROM test"


به شکل پیشفرض کوئری ها برای 30 ثانیه کش میشن. اگر تمایل داشتید برای هر کوئری زمان متفاوتی رو درنظر بگیرید، بدین صورت عمل کنید، مثلاً برای کش 1 روزه:
کد: انتخاب همه
"/*qc_tt=86400*/SELECT id FROM test"

و یا بهتر از اون اینطوری:
کد: انتخاب همه
"/*" . MYSQLND_QC_TTL_SWITCH . "86400*/" . "SELECT id FROM test"

که در نهایت برای ترکیب پارامتر مربوط به فعالسازی و تنظیم زمان کش، به یه چنین دستوری خواهید رسید:
کد: انتخاب همه
$sql = sprintf("/*%s*//*%s%d*/SELECT id FROM test WHERE id = 1", MYSQLND_QC_ENABLE_SWITCH, MYSQLND_QC_TTL_SWITCH, 2);


که خروجی اون چنین خواهد بود:
کد: انتخاب همه
/*qc=on*//*qc_ttl=2*/SELECT id FROM test WHERE id = 1


که دستور فوق ضمن فعال سازی کش روی کوئری اون رو برای 2 ثانیه کش میکنه.

حالا اینها که همه رشته اضافه در کوئری دارند و در ابتدای مطلب، اشاره به عدم نیاز به تغییر کوئری ها بود، درسته! اینها برای مواقعی بود که تصمیم دارید پیشفرض این ویژگی غیرفعال باشه و به دلخواه روی کوئری های خاص کش اعمال بشه.
اما برای اینکه کش به شکل پیشفرض فعال باشه کافیه در php.ini دستور زیر را وارد کنید:
کد: انتخاب همه
mysqlnd_qc.cache_by_default = 1
mysqlnd_qc.ttl = 86400


بدین ترتیب و به همین سادگی، بدون اینکه هیچ تغییری در کوئری های برنامتون بدید، همه کوئری ها برای مدت 1 روز کش خواهند شد.

توسط تابع mysqlnd_qc_clear_cache در PHP که ورودر و خروجی هم نداره، میتونید کش رو ریست کنید.

دستورات و تنظیمات خیلی بیشتر هستند که در این مطلب سعی شد خلاصه و کلیدی موارد پرکاربرد بیان بشن، برای جزئیات بیشتر از لینک های زیر استفاده کنید:


توضیحات و راهنمای بیشتر:
https://php.net/manual/en/mysqlnd-qc.qu ... aching.php

تنظیمات بیشتر:
https://www.php.net/manual/en/mysqlnd-q ... ration.php

توابع بیشتر:
https://www.php.net/manual/en/ref.mysqlnd-qc.php


--نبی کرمعلی‌زاده

بازگشت به مقالات آموزشی PHP

چه کسی آنلاین است

کاربران حاضر در این انجمن : کاربر عضو شده ای موجود نیست و 0 مهمان