<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>jQueryTips by Tee++; &#187; caching</title>
	<atom:link href="http://www.jquerytips.com/tag/caching/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.jquerytips.com</link>
	<description>Coding is fun.</description>
	<lastBuildDate>Sun, 25 Apr 2010 11:30:33 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>บทความว่าด้วยการ optimize code ด้วยการทำ caching</title>
		<link>http://www.jquerytips.com/2008/04/07/optimize-code-caching/</link>
		<comments>http://www.jquerytips.com/2008/04/07/optimize-code-caching/#comments</comments>
		<pubDate>Mon, 07 Apr 2008 15:40:09 +0000</pubDate>
		<dc:creator>Tee++;</dc:creator>
				<category><![CDATA[Others]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[optimize]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://www.jquerytips.com/2008/04/07/%e0%b8%9a%e0%b8%97%e0%b8%84%e0%b8%a7%e0%b8%b2%e0%b8%a1%e0%b8%a7%e0%b9%88%e0%b8%b2%e0%b8%94%e0%b9%89%e0%b8%a7%e0%b8%a2%e0%b8%81%e0%b8%b2%e0%b8%a3-optimize-code-%e0%b8%94%e0%b9%89%e0%b8%a7%e0%b8%a2/</guid>
		<description><![CDATA[ตัวผมเองนั้นมีประสบการณ์ไม่ดีกับปัญหา MySQL จนเกือบจะเลิกใช้มันไปแล้วครั้งนึง จนหาทาง optimize code แบบต่างๆออกมาซึ่งได้ผลดีบ้างน้อยบ้างตามแต่จะว่ากัน ดังนี้
1. query database I/O ธรรมดา
:ผลลัพธ์ คนเข้าเยอะ โฮสเดี้ยง เวบล่ม โดนด่า
2. ทำ index ให้กับ db
:ผลลัพธ์ สามารถใช้ได้แค่เป็นส่วนประกอบของการทำ optimize code เท่านั้น แต่ถือว่า &#8220;จำเป็น&#8221; เลยทีเดียว
3. ทำการ cache output ออกมาเป็น static (html)
:ผลลัพธ์ ดีทีเดียว แต่มีปัญหาเรื่องความสดของข้อมูล manage เรื่อง fresh content ยาก
4. ทำการเปลี่ยนเป็น flat db (text, xml, etc.)
:ผลลัพธ์ ใช้ได้เลย แต่มีปัญหาเรื่องการเขียนข้อมูลพร้อมกันทีละหลายคน lock ไม่ทัน ไฟล์ตาย ข้อมูล write มาไม่ครบ backup [...]]]></description>
			<content:encoded><![CDATA[<p>ตัวผมเองนั้นมีประสบการณ์ไม่ดีกับปัญหา MySQL จนเกือบจะเลิกใช้มันไปแล้วครั้งนึง จนหาทาง optimize code แบบต่างๆออกมาซึ่งได้ผลดีบ้างน้อยบ้างตามแต่จะว่ากัน ดังนี้</p>
<p>1. query database I/O ธรรมดา<br />
:ผลลัพธ์ คนเข้าเยอะ โฮสเดี้ยง เวบล่ม โดนด่า</p>
<p>2. ทำ index ให้กับ db<br />
:ผลลัพธ์ สามารถใช้ได้แค่เป็นส่วนประกอบของการทำ optimize code เท่านั้น แต่ถือว่า &#8220;จำเป็น&#8221; เลยทีเดียว</p>
<p>3. ทำการ cache output ออกมาเป็น static (html)<br />
:ผลลัพธ์ ดีทีเดียว แต่มีปัญหาเรื่องความสดของข้อมูล manage เรื่อง fresh content ยาก<span id="more-24"></span></p>
<p>4. ทำการเปลี่ยนเป็น flat db (text, xml, etc.)<br />
:ผลลัพธ์ ใช้ได้เลย แต่มีปัญหาเรื่องการเขียนข้อมูลพร้อมกันทีละหลายคน lock ไม่ทัน ไฟล์ตาย ข้อมูล write มาไม่ครบ backup ลำบาก</p>
<p>จนมาถึงวิธีที่ผมใช้มาจนปัจจุบัน เหมาะมากๆกับการที่มีคนเข้าจำนวนหลัก หมื่น จนถึง หลักแสน</p>
<p>ซึ่งวิธีที่ดีที่สุดในตอนนี้คงหนีไม่พ้นการทำ cache ใส่ memory โดยตรงพวก โดยใช้ extensions พวก apc, memcache</p>
<p>ซึ่งการทำแบบนี้ให้ผลลัพธ์ที่ดีในระดับ &#8220;พระเจ้า&#8221; เวบจะเร็วขึ้นอย่างทันตาเห็น เพราะ cache จะถูกทำใน fast memory ซึ่งมีความเร็วเป็นทุนเดิมอยู่แล้ว และเมื่อขอ้มูลเต็มจะมีการ clear เอาของที่เก่าออกเอง</p>
<p>แต่ทว่า&#8230;.</p>
<p>ข้อเสียคือต้องลงทุนไปตั้ง Server เองเพราะไม่มี share hosting ที่ไหนให้เรามา แชร์ ram มันหรอกจริงมั้ยครับ T_T</p>
<p>ฉะนั้นเราก็จะมาทำกันง่ายๆก่อนด้วยการทำ cache ในระดับ file </p>
<p>ซึ่งง่ายที่สุดประหยัดค่าใช้จ่ายที่สุด ที่สำคัญลงมือทำได้เลย</p>
<p>************************************<br />
รูปแบบของcache จะแบ่งออกเป็น hit กับ miss ซึ่ง hit หมายถึง user เรียกข้อมูลใช้จาก cache ได้ทันทีซึ่งเป็น &#8220;ตัวดี&#8221; ส่วน miss คือ user ไม่สามารถเรียกใช้ cache ได้ในกรณีต่างๆ ซึ่งเป็น &#8220;ตัวไม่ดี&#8221;</p>
<p>ถ้าเราใช้ cache แบบ memory เราสามารถจะวัดผลได้เลยว่ามี hit กี่ % แต่ถ้าเป็น file ก็คงต้องให้ admin มา monitor กันละครับ เอาเป็นว่า ลืมไปก่อนละกัน อิอิ</p>
<p>แต่ว่าการเริ่ม cache ทุกครั้งจะต้องเริ่มจาก miss ก่อนเสมอ คือ</p>
<p>1. user เข้ามาครั้งแรกเรียกข้อมูลจาก cache ไม่เจอ<br />
2. ดึงข้อมูลโดยตรงจาก db (miss)<br />
3. ทำการสร้าง cache จากข้อมูลที่ user ดึง<br />
4. user เข้ามาครั้งที่ 2 เรียกข้อมูลจาก cache เจอ เรียกใช้ได้ทันที (hit)</p>
<p>ทีเหลือต้องไป manage ความสดใหม่ของ cache เอาเอง เช่น</p>
<p>1. user ทำการอัพเดท profile ลบ cache ทิ้งรอให้ user สร้าง cache ด้วยตัวเอง ซึ่งแน่นอนจะเกิด miss อีก 1 ที</p>
<p>หรือจะทำงานหนักขึ้น (coding)</p>
<p>2. user ทำการอัพเดท profile แล้วเราอัพเดท cache ทันที ไม่รอให้เกิดการ miss</p>
<p>************************************<br />
ลองมาดูตัวอย่างการทำ cache จากผลลัพธ์ การ query อย่างง่ายๆ กันก่อน</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$cache</span> = <span class="st0">&quot;cache/&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$key</span> = <span class="st0">&quot;your_key&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2"><span class="kw1">if</span> <span class="br0">&#40;</span>!<span class="re0">$data</span> = <a href="http://www.php.net/file_get_contents"><span class="kw3">file_get_contents</span></a><span class="br0">&#40;</span><span class="re0">$cache</span>.<span class="re0">$key</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="re0">$sql</span> = <span class="st0">&quot;SELECT &#8230;&#8230;.&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="co1">//&#8230;&#8230; query step &#8230;&#8230; (ละไว้ในฐานที่เข้าใจ)</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="re0">$data</span> = <span class="re0">$results</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; file_put_contents<span class="br0">&#40;</span><span class="re0">$cache</span>.<span class="re0">$key</span>, <span class="re0">$data</span><span class="br0">&#41;</span>; <span class="co1">// php5 only!</span></div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><a href="http://www.php.net/print_r"><span class="kw3">print_r</span></a><span class="br0">&#40;</span><span class="re0">$data</span><span class="br0">&#41;</span>; <span class="co1">// ทดสอบข้อมูล</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">?&gt;</span></div>
</li>
</ol>
</div>
<p>ตามโคดข้างบนจะเป็นการเรียกcache ถ้าไม่มีก็ให้ทำการสร้าง cache ซึ่งโคดตัวนี้ผมแค่เขียนเป็นแนวทางเพื่อให้เห็นภาพ แต่ว่ามันใช้ไม่ได้จริงๆ แหะๆ เพราะจุดอ่อนมากมายเช่นไม่มีการตั้ง cache expire ไม่มีการ lock ข้อมูลระหว่างเขียนไม่สามารลบ cache ออกได้เอง</p>
<p>ซึ่งตามปกติคนที่จะใช้ cache ในลักษณะนี้มักจะเขียน class ขึ้นมา 1 ตัวเพื่อทำหน้าที่ในส่วน</p>
<p>1. การ store ค่าลง cache พร้อมระบุเวลาหมดอายุ รวทั้ง key<br />
2. การ fetch ค่าที่ยังไม่หมดอายุ จาก cache โดยใช้ key อ้างอิง<br />
3. การ ลบค่า ออกจาก cache โดยการระบุ key<br />
4. การ clear cache ทั้งหมด</p>
<p>ซึ่งลองดูตัวอย่างได้จากlink ด้านล่าง เอา class ไปใช้ได้เลยหรือจะปรับปรุงให้ดีขึ้นตามสไตล์ก็แล้วแต่ ในที่นี้ผมเห็นมี class ที่ทำงานกับ 3 แบบเลยคือ file,apc, memcache ลองดูแล้วกันครับ</p>
<p>http://www.rooftopsolutions.nl/article/107</p>
<p>************************************<br />
ข้อพึงระวังในการทำ File Cache ก็คือพยายามอย่าเก็บไฟล์ cache ไว้ที่ folder เดียว เพราะมันจะมีปัญหาเรื่องการ seek ข้อมูลอีก -*-</p>
<p>โดยอาจจะใช้อัลกอลิทึ่มสักตัวมาคำนวนว่า cache นี้ควรจะเก็บไว้ที่โฟลเดอร์ไหน ตัวอย่าง</p>
<p><code>$cache = "cache/';<br />
$key = "mykey";<br />
$sub = (strlen($key)%9);</p>
<p>$cache.=$sub."/"; // ควรจะได้ค่าเป็น cache/5/</code></p>
<p>ซึ่งแบบนี้เท่ากับว่าเราจะมี cache/ เป็น directory ที่เก็บหลัก ข้างในยังแบ่งย่อยได้อีก 9 เพราะ mod 9</p>
<p>หรือจะใช้วิธีตัดตัวอักษรตัวแรก แล้วทำเป็นโฟลเดอร์ย่อย คือ 1-9 a-z รอไว้เลยก็ได้</p>
<p>แต่ถ้าวันไหนเกิดcache เต็มก็ลบออกไปหมด แล้วให้มัน built ใหม่ยังดีกว่าให้มัน fetch ค่าจาก db ที่เผลอๆ บางที join กัน 5-10 ตาราง ตรงๆ แน่นอน</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jquerytips.com/2008/04/07/optimize-code-caching/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
