<?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>jQuery, Ajax, PHP, JSON, XML, Web Technologies &#187; MySQL</title>
	<atom:link href="http://blog.chonla.com/tag/mysql/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.chonla.com</link>
	<description>คุยกันเรื่อง jQuery, Ajax, PHP, JSON, XML และ Web Technologies เป็นภาษาไทยกันดีกว่า</description>
	<lastBuildDate>Tue, 17 Jan 2012 18:27:02 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Transaction ใน Database นั้นสำคัญไฉน</title>
		<link>http://blog.chonla.com/2011/07/transaction-%e0%b9%83%e0%b8%99-database-%e0%b8%99%e0%b8%b1%e0%b9%89%e0%b8%99%e0%b8%aa%e0%b8%b3%e0%b8%84%e0%b8%b1%e0%b8%8d%e0%b9%84%e0%b8%89%e0%b8%99/</link>
		<comments>http://blog.chonla.com/2011/07/transaction-%e0%b9%83%e0%b8%99-database-%e0%b8%99%e0%b8%b1%e0%b9%89%e0%b8%99%e0%b8%aa%e0%b8%b3%e0%b8%84%e0%b8%b1%e0%b8%8d%e0%b9%84%e0%b8%89%e0%b8%99/#comments</comments>
		<pubDate>Thu, 28 Jul 2011 18:41:28 +0000</pubDate>
		<dc:creator>chonla</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[ACID]]></category>
		<category><![CDATA[Transaction]]></category>

		<guid isPermaLink="false">http://blog.chonla.com/?p=332</guid>
		<description><![CDATA[โพสนี้ว่าด้วยเรื่องทฤษฎีเกี่ยวกับ transaction ใน database ล้วน ๆ พร้อมตัวอย่างประกอบให้เห็นนิดหน่อยครับ สืบเนื่องจากโพสก่อนหน้านี้ผมพูดถึง database engine ใน MySQL ไป โดยอธิบายไปว่า บางชนิดจะสนับสนุน transaction แต่บางชนิดไม่สนับสนุน แถมยังเอาลิงก์เกี่ยวกับ transaction ทิ้งไว้ให้ไปอ่านเองอีกด้วย โพสนี้เลยจะขออนุญาตมาขยายความเรื่องเกี่ยวกับ transaction ให้เห็นภาพชัดเจนมากขึ้นกันดีกว่า Transaction (ทรานแซคชั่น) หมายถึงการดำเนินการธุรกรรมอะไรซักอย่าง แล้วแต่เนื้อหาที่นำไปใช้ เช่น ไปธนาคารถอนเงิน 1 ครั้ง ก็เรียกได้ว่าเกิด 1 transaction หรือโอนเงินให้เพื่อน 1 ครั้ง ก็เรียกว่า 1 transaction ได้เช่นกัน แล้วความสำคัญของ transaction มันอยู่ตรงไหน?&#8230; ลองพิจารณากระบวนการโอนเงินดูครับ (ตัวอย่างคลาสสิคมาก) ผมโอนเงินจากบัญชี A ไปบัญชี B กระบวนการย่อยที่เกิดขึ้นคือ ถอนเงินจาก A และฝากเข้าไปที่ B [...]]]></description>
			<content:encoded><![CDATA[<p>โพสนี้ว่าด้วยเรื่องทฤษฎีเกี่ยวกับ transaction ใน database ล้วน ๆ พร้อมตัวอย่างประกอบให้เห็นนิดหน่อยครับ</p>
<p>สืบเนื่องจากโพสก่อนหน้านี้ผมพูดถึง database engine ใน MySQL ไป โดยอธิบายไปว่า บางชนิดจะสนับสนุน transaction แต่บางชนิดไม่สนับสนุน แถมยังเอาลิงก์เกี่ยวกับ transaction ทิ้งไว้ให้ไปอ่านเองอีกด้วย โพสนี้เลยจะขออนุญาตมาขยายความเรื่องเกี่ยวกับ transaction ให้เห็นภาพชัดเจนมากขึ้นกันดีกว่า</p>
<p><span id="more-332"></span>Transaction (ทรานแซคชั่น) หมายถึงการดำเนินการธุรกรรมอะไรซักอย่าง แล้วแต่เนื้อหาที่นำไปใช้ เช่น ไปธนาคารถอนเงิน 1 ครั้ง ก็เรียกได้ว่าเกิด 1 transaction หรือโอนเงินให้เพื่อน 1 ครั้ง ก็เรียกว่า 1 transaction ได้เช่นกัน แล้วความสำคัญของ transaction มันอยู่ตรงไหน?&#8230; ลองพิจารณากระบวนการโอนเงินดูครับ (ตัวอย่างคลาสสิคมาก) ผมโอนเงินจากบัญชี A ไปบัญชี B กระบวนการย่อยที่เกิดขึ้นคือ ถอนเงินจาก A และฝากเข้าไปที่ B ดังนั้นเราจะเห็นได้ว่า ในธุรกรรมการโอนเงิน 1 transaction จะมี 2 operation ย่อยเกิดขึ้นคือ ถอนเงิน และฝากเงิน</p>
<p>ปัญหาคือ ในกรณีที่ระบบล่มระหว่าง transaction ยังไม่เสร็จสิ้นล่ะ (จากตัวอย่าง เช่น ถอนเงินจาก A มาแล้ว แต่ยังไม่ได้ฝากเข้าไปที่ B) จะเกิดอะไรขึ้น&#8230; งานงอกไงครับ</p>
<p>ดังนั้น ไอ้เจ้า transaction เนี่ย อย่างน้อยจำเป็นต้องมีคุณสมบัติที่จะทำให้เรามั่นใจได้ว่า กระบวนการย่อย ๆ ที่เกิดใน transaction เนี่ย ทำงานได้อย่างสมบูรณ์นะ คุณสมบัติพวกนี้ถ้าเอาเฉพาะตัวอักษรตัวแรกของชื่อภาษาอังกฤษมาเรียงกัน จะเขียนได้เป็น ACID ดังนั้น คุณสมบัติของ transaction นี้ก็จะเรียกง่าย ๆ กันว่า ACID properties ของ transaction นั่นเอง โดยที่ ACID properties นี้จะประกอบด้วย</p>
<blockquote><p><span style="color: #808080;">ก่อนที่จะทำความรู้จัก ACID properties &#8230; ผมขอแนะนำให้รู้จักคำ 2 คำที่ใช้กันใน transaction ก่อน คือ rollback และ commit &#8230; การ <em><strong>rollback</strong></em> หมายถึงการยกเลิกสิ่งที่ทำมาทั้งหมดใน transaction นั้น ๆ ส่วนการ <em><strong>commit</strong></em> คือการยอมรับและบันทึกค่าที่เปลี่ยนแปลงทั้งหมดใน transaction นั้น ๆ</span></p></blockquote>
<p>1. Atomicity &#8211; คุณสมบัตินี้จะสอดคล้องกับตัวอย่างที่ผมพูดไปก่อนหน้านี้ โดยจะมีหลักง่าย ๆ ที่ชัดเจนคือ transaction ที่ถูกกระทำนี้มี operation ย่อย ๆ หลายคำสั่ง ถ้าทำได้ ก็หมายถึงทำได้ทั้งหมด ถ้าทำอันใดอันหนึ่งไม่ได้ จะหมายถึงทำไม่ได้เลยตั้งแต่คำสั่งแรก (All or nothing)</p>
<p>2. Consistency &#8211; คุณสมบัตินี้หมายถึงว่า ความสอดคล้องของข้อมูลจะต้องถูกต้องเสมอ ถ้าไม่ถูกต้องระบบจะต้องทำการ rollback กลับไปยังจุดที่ข้อมูลทั้งหมดสอดคล้องกันอยู่ ยกตัวอย่างเช่น จำนวนเงินที่ก่อนที่จะทำการโอนของทั้ง 2 บัญชีรวมกันจะต้องเท่ากันกับหลักจากทำการโอนแล้ว หรือข้อมูลที่เก็บเฉพาะ integer แต่เราใส่ข้อมูลที่เป็นทศนิยมเข้าไป ข้อมูลทั้งเรคอร์ดนี้ก็ไม่ควรถูกบันทึก หรือในระบบฐานข้อมูลที่มีการกำหนดฟิลด์อ้างอิงได้ (ว่าฟิลด์นี้อ้างถึงฟิลด์ไหนในตารางอื่น) การลบเรคอร์ดที่มีฟิลด์ที่ถูกอ้างอิงก็ควรจะก่อให้เกิด &#8230;</p>
<ul>
<li>ยกเลิก transaction และ rollback กลับไปยังจุดที่สอดคล้องล่าสุด&#8230;หรือ</li>
<li>ลบเรคอร์ดที่มีการอ้างถึงข้อมูลนี้&#8230;หรือ</li>
<li>ทำฟิลด์ที่อ้างถึงข้อมูลนี้ให้เป็น NULL ซะ</li>
</ul>
<p>3. Isolation &#8211; หมายถึงว่า การประมวลผล transaction หนึ่ง ๆ ถ้ามันยังไม่เสร็จ transaction อื่น ๆ จะต้องไม่เห็นผลจากการกระทำของ transaction นี้ เช่น transaction ที่ 1 โอนเงินจากบัญชี A ไป B จำนวน 200 บาท และ transaction ที่ 2 คือ ถอนเงินจาก A 100 บาท กำหนดให้ในขั้นตอนของ transaction ที่ 2 เกิดขึ้นหลังจากที่ถอนเงินออกจาก A ไป 200 เพื่อที่จะนำไปฝากเข้า B แล้ว จากคุณสมบัติของ Isolation นี้จะทำให้ transaction ที่ 2 ยังไม่เห็นว่า A เงินหายไปแล้ว 200 หรือ B ได้รับเงินแล้ว 200</p>
<p>4. Durability &#8211; หมายถึง transaction ใด ๆ ก็ตามที่ทำการ commit แล้ว ข้อมูลจะต้องอยู่แบบนั้น ไม่ว่าระบบจะล่มยังไง เมื่อกู้คืนมาได้ transaction นั้นก็จะยังถือว่า commit และประมวลผลเสร็จสิ้นแล้ว</p>
<p>ครบ 4 อย่างแล้ว&#8230; พอเห็นภาพความสำคัญของ transaction ใน database มากขึ้นแล้วหรือยังครับ</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fblog.chonla.com%2F2011%2F07%2Ftransaction-%25e0%25b9%2583%25e0%25b8%2599-database-%25e0%25b8%2599%25e0%25b8%25b1%25e0%25b9%2589%25e0%25b8%2599%25e0%25b8%25aa%25e0%25b8%25b3%25e0%25b8%2584%25e0%25b8%25b1%25e0%25b8%258d%25e0%25b9%2584%25e0%25b8%2589%25e0%25b8%2599%2F&amp;title=Transaction%20%E0%B9%83%E0%B8%99%20Database%20%E0%B8%99%E0%B8%B1%E0%B9%89%E0%B8%99%E0%B8%AA%E0%B8%B3%E0%B8%84%E0%B8%B1%E0%B8%8D%E0%B9%84%E0%B8%89%E0%B8%99" id="wpa2a_2"><img src="http://blog.chonla.com/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://blog.chonla.com/2011/07/transaction-%e0%b9%83%e0%b8%99-database-%e0%b8%99%e0%b8%b1%e0%b9%89%e0%b8%99%e0%b8%aa%e0%b8%b3%e0%b8%84%e0%b8%b1%e0%b8%8d%e0%b9%84%e0%b8%89%e0%b8%99/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ทำความรู้จักกับ Storage Engine ของ MySQL กันหน่อย</title>
		<link>http://blog.chonla.com/2011/07/%e0%b8%97%e0%b8%b3%e0%b8%84%e0%b8%a7%e0%b8%b2%e0%b8%a1%e0%b8%a3%e0%b8%b9%e0%b9%89%e0%b8%88%e0%b8%b1%e0%b8%81%e0%b8%81%e0%b8%b1%e0%b8%9a-storage-engine-%e0%b8%82%e0%b8%ad%e0%b8%87-mysql-%e0%b8%81/</link>
		<comments>http://blog.chonla.com/2011/07/%e0%b8%97%e0%b8%b3%e0%b8%84%e0%b8%a7%e0%b8%b2%e0%b8%a1%e0%b8%a3%e0%b8%b9%e0%b9%89%e0%b8%88%e0%b8%b1%e0%b8%81%e0%b8%81%e0%b8%b1%e0%b8%9a-storage-engine-%e0%b8%82%e0%b8%ad%e0%b8%87-mysql-%e0%b8%81/#comments</comments>
		<pubDate>Tue, 26 Jul 2011 16:01:11 +0000</pubDate>
		<dc:creator>chonla</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Database Engines]]></category>

		<guid isPermaLink="false">http://blog.chonla.com/?p=327</guid>
		<description><![CDATA[MySQL พูดชื่อนี้ ผมว่า developer หลาย ๆ คน ก็คงต้องรู้จักฐานข้อมูลยอดนิยมตัวนี้ แต่จะมีใครรู้บ้างว่า MySQL เนี่ย มันมี storage engine ให้เลือกใช้หลายแบบนะ แล้วแบบไหนที่เหมาะกับงานของเราล่ะ? (ใครไม่รู้จักว่า storage engine นั้นหมายถึงอะไร database engine เรียกง่าย ๆ ก็เหมือนชนิดของฐานข้อมูล สาเหตุที่เราต้องเลือกชนิด engine ให้เหมาะสมนั้น เปรียบเทียบง่าย ๆ ว่า มันก็เหมือนกับเสื้อผ้า เสื้อผ้ามีหลายประเภท เราใส่ออกไปนอกบ้านได้ทุกแบบ แต่แบบไหนที่เหมาะกับกาลเทศะ และงานที่ทำ อย่างเช่น ชุดกันไฟกับงานนักดับเพลิง จะให้ใส่สูทไปดับไฟก็ได้ แต่มันไม่ถนัด&#8230;) การที่เราจะรู้ว่า storage engine แบบไหนเหมาะกับเรานั้น เราก็ต้องมาทำความรู้จักกับ storage engine แต่ละชนิดกันก่อน เพื่อไม่ให้เป็นการเสียเวลา เรามาทำความรู้จักกับ storage engine แต่ละตัวกันดีกว่า (เราสามารถกำหนดให้แต่ละตารางใช้ engine ต่างกันได้ตามความเหมาะสมในการใช้งาน) ISAM เป็น storage engine ที่ถูกออกแบบมาโดยที่มีแนวคิดที่ว่า ตารางมักจะถูกอ่านมากกว่าอัพเดท [...]]]></description>
			<content:encoded><![CDATA[<p>MySQL พูดชื่อนี้ ผมว่า developer หลาย ๆ คน ก็คงต้องรู้จักฐานข้อมูลยอดนิยมตัวนี้ แต่จะมีใครรู้บ้างว่า MySQL เนี่ย มันมี storage engine ให้เลือกใช้หลายแบบนะ แล้วแบบไหนที่เหมาะกับงานของเราล่ะ? (ใครไม่รู้จักว่า storage engine นั้นหมายถึงอะไร database engine เรียกง่าย ๆ ก็เหมือนชนิดของฐานข้อมูล สาเหตุที่เราต้องเลือกชนิด engine ให้เหมาะสมนั้น เปรียบเทียบง่าย ๆ ว่า มันก็เหมือนกับเสื้อผ้า เสื้อผ้ามีหลายประเภท เราใส่ออกไปนอกบ้านได้ทุกแบบ แต่แบบไหนที่เหมาะกับกาลเทศะ และงานที่ทำ อย่างเช่น ชุดกันไฟกับงานนักดับเพลิง จะให้ใส่สูทไปดับไฟก็ได้ แต่มันไม่ถนัด&#8230;)</p>
<p>การที่เราจะรู้ว่า storage engine แบบไหนเหมาะกับเรานั้น เราก็ต้องมาทำความรู้จักกับ storage engine แต่ละชนิดกันก่อน เพื่อไม่ให้เป็นการเสียเวลา เรามาทำความรู้จักกับ storage engine แต่ละตัวกันดีกว่า (เราสามารถกำหนดให้แต่ละตารางใช้ engine ต่างกันได้ตามความเหมาะสมในการใช้งาน)</p>
<p><span id="more-327"></span></p>
<ul>
<li>ISAM เป็น storage engine ที่ถูกออกแบบมาโดยที่มีแนวคิดที่ว่า ตารางมักจะถูกอ่านมากกว่าอัพเดท ทำให้ storage engine ชนิดนี้สามารถประมวลผลคำสั่งที่เป็นการอ่านได้อย่างรวดเร็วมาก ๆ แต่มีข้อเสียใหญ่ ๆ คือการไม่สนับสนุนการทำงานแบบ transaction (คือไม่สามารถ rollback ได้ ถ้าเกิดกรณีการทำงานไม่สมบูรณ์ ทางทฤษฎีเรียกว่า ACID transaction properties : สามารถอ่านเพิ่มเติมได้จากที่ <a href="http://en.wikipedia.org/wiki/ACID">http://en.wikipedia.org/wiki/ACID</a>)  และไม่รองรับระบบ fault-tolerant (คือถ้าระบบล่ม ก็อาจจะไม่สามารถที่จะกู้ข้อมูลกลับขึ้นมาได้เลย) ดังนั้นถ้าจะใช้ engine นี้ในงานสำคัญ ก็แนะนำว่าหมั่น backup บ่อย ๆ ครับ</li>
<li>MyISAM เป็น engine ยอดนิยมสำหรับเว็บทั่ว ๆ ไป พัฒนาต่อเนื่องมาจาก ISAM ทำให้ความเร็วในการอ่านยังเป็นเรื่องที่โดดเด่นอยู่เหมือนเดิม นอกจากนี้แล้วยังมีการเพิ่มส่วนของการทำ indexing และ operation สำหรับ field บางอย่างลงไปด้วย ข้อดีอีกอย่างคือ ใน MyISAM นี้ มี tool ที่ใช้ในการกู้ข้อมูลในกรณีที่ตารางมีปัญหาด้วย (MyISAMChk) แต่ข้อเสียที่สำคัญก็ยังคงอยู่คือ ไม่สนับสนุนการทำงานแบบ transaction และคำสั่ง update ยังส่งผลให้เกิดขยะที่ไม่จำเป็นอีกด้วย ทำให้เราต้องใช้คำสั่ง OPTIMIZE เพื่อจัดการขยะพวกนี้ให้หายไปจากตาราง</li>
<li>HEAP (หรือ Memory) เป็น engine ที่ไม่ได้สร้างตารางขึ้นมาเป็นไฟล์จริง ๆ เหมือนกับ engine อื่น ๆ แต่จะสร้างตารางลงใน Memory ของเครื่อง ทำให้การเข้าถึงทำได้รวดเร็วยิ่งกว่า ISAM และ MyISAM แต่ข้อเสียคือ มันไม่อยู่ถาวร ถ้ามีการปิดเครื่องหรือระบบล่มโดยที่ยังไม่ได้บันทึกค่าในตารางลงไฟล์ ข้อมูลใน Memory ขณะนั้นก็จะหายไปทั้งหมด ไม่สามารถกู้คืนได้ และทุกครั้งที่ใช้งานตารางที่ใช้ engine นี้เสร็จ ก็จะต้องลบตารางนี้ทิ้งด้วย ไม่เช่นนั้นแล้วจะเกิดขยะใน Memory อาจจะทำให้ Memory ไม่พอในการทำงานได้</li>
<li>InnoDB และ Berkley DB (BDB) เป็นฐานข้อมูลที่ถูกพัฒนามาให้สนับสนุน transaction และแถมด้วยการสนับสนุน Foreign Key แต่ก็มีข้อเสียคือมันช้ากว่า ISAM และ MyISAM แต่สำหรับผู้ที่จำเป็นจะต้องใช้ transaction แล้ว ก็คงเลี่ยงไม่ได้ที่จะใช้ engine ชนิดนี้</li>
<li>Cluster ถูกพัฒนาขึ้นเพื่อเพิ่ม High Availability และ High Performance (ประมาณว่าใช้งานได้นาน ๆ และมีประสิทธิภาพดี) แต่ก็จะต้องใช้ resource ในการ implement ค่อนข้างมากเช่นเดียวกัน โดยที่ engine สำหรับ Cluster นี้มีชื่อว่า NDB หรือ NDBCLUSTER (NDB = Network Database)</li>
</ul>
<div>(จริง ๆ แล้วมี storage engine อีกมากมายที่ถูกพัฒนาขึ้นมาใช้กับ MySQL แต่ผมขอไม่พูดถึง เพราะมันเยอะมาก และเราก็ไม่ค่อยได้ใช้งานเท่าไรนัก ผู้ที่สนใจ เข้าไปดูรายละเอียดได้ที่ <a href="http://en.wikipedia.org/wiki/MySQL">http://en.wikipedia.org/wiki/MySQL</a>)</div>
<div>ถึงตอนนี้ ผมว่าเราคงสามารถที่จัดตัดสินใจได้ง่ายขึ้นแล้วว่าจะใช้ engine แบบไหนกับตารางของเราดี</div>
<div>อ้างอิง</div>
<div>
<ul>
<li><a href="http://www.techrepublic.com/article/a-fast-and-furious-guide-to-mysql-database-engines/1058872">http://www.techrepublic.com/article/a-fast-and-furious-guide-to-mysql-database-engines/1058872</a></li>
<li><a href="http://en.wikipedia.org/wiki/MySQL">http://en.wikipedia.org/wiki/MySQL</a></li>
<li><a href="http://en.wikipedia.org/wiki/MySQL_Cluster">http://en.wikipedia.org/wiki/MySQL_Cluster</a></li>
</ul>
</div>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fblog.chonla.com%2F2011%2F07%2F%25e0%25b8%2597%25e0%25b8%25b3%25e0%25b8%2584%25e0%25b8%25a7%25e0%25b8%25b2%25e0%25b8%25a1%25e0%25b8%25a3%25e0%25b8%25b9%25e0%25b9%2589%25e0%25b8%2588%25e0%25b8%25b1%25e0%25b8%2581%25e0%25b8%2581%25e0%25b8%25b1%25e0%25b8%259a-storage-engine-%25e0%25b8%2582%25e0%25b8%25ad%25e0%25b8%2587-mysql-%25e0%25b8%2581%2F&amp;title=%E0%B8%97%E0%B8%B3%E0%B8%84%E0%B8%A7%E0%B8%B2%E0%B8%A1%E0%B8%A3%E0%B8%B9%E0%B9%89%E0%B8%88%E0%B8%B1%E0%B8%81%E0%B8%81%E0%B8%B1%E0%B8%9A%20Storage%20Engine%20%E0%B8%82%E0%B8%AD%E0%B8%87%20MySQL%20%E0%B8%81%E0%B8%B1%E0%B8%99%E0%B8%AB%E0%B8%99%E0%B9%88%E0%B8%AD%E0%B8%A2" id="wpa2a_4"><img src="http://blog.chonla.com/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://blog.chonla.com/2011/07/%e0%b8%97%e0%b8%b3%e0%b8%84%e0%b8%a7%e0%b8%b2%e0%b8%a1%e0%b8%a3%e0%b8%b9%e0%b9%89%e0%b8%88%e0%b8%b1%e0%b8%81%e0%b8%81%e0%b8%b1%e0%b8%9a-storage-engine-%e0%b8%82%e0%b8%ad%e0%b8%87-mysql-%e0%b8%81/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Sync ข้อมูลจำนวนนับจากตารางอื่นด้วย subquery</title>
		<link>http://blog.chonla.com/2011/06/sync-%e0%b8%82%e0%b9%89%e0%b8%ad%e0%b8%a1%e0%b8%b9%e0%b8%a5%e0%b8%88%e0%b8%b3%e0%b8%99%e0%b8%a7%e0%b8%99%e0%b8%99%e0%b8%b1%e0%b8%9a%e0%b8%88%e0%b8%b2%e0%b8%81%e0%b8%95%e0%b8%b2%e0%b8%a3%e0%b8%b2/</link>
		<comments>http://blog.chonla.com/2011/06/sync-%e0%b8%82%e0%b9%89%e0%b8%ad%e0%b8%a1%e0%b8%b9%e0%b8%a5%e0%b8%88%e0%b8%b3%e0%b8%99%e0%b8%a7%e0%b8%99%e0%b8%99%e0%b8%b1%e0%b8%9a%e0%b8%88%e0%b8%b2%e0%b8%81%e0%b8%95%e0%b8%b2%e0%b8%a3%e0%b8%b2/#comments</comments>
		<pubDate>Mon, 20 Jun 2011 18:42:40 +0000</pubDate>
		<dc:creator>chonla</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Performance Tuning]]></category>
		<category><![CDATA[Subquery]]></category>

		<guid isPermaLink="false">http://blog.chonla.com/?p=324</guid>
		<description><![CDATA[ถ้าว่าตามทฤษฎีฐานข้อมูลแล้วนั้น การ Normalization ตารางเพื่อลดความซ้ำซ้อนของข้อมูล (Redundancy) เป็นสิ่งที่จำเป็นมาก แต่ในการใช้งานจริง การ Normalization ที่มากเกินไป อาจจะก่อผลเสียได้ ยกตัวอย่างเช่น หน้าแสดงกระทู้ในเว็บบอร์ด X จะแสดงข้อมูลจำนวน comment ที่สมาชิกเข้ามาตอบในหัวข้อนั้น ๆ ถ้าเราทำ Normalization ตารางของเว็บบอร์ดตามทฤษฎี โดยให้ตารางที่เก็บความคิดเห็น (comment) แยกจากกระทู้ (topic) ในตาราง comment มี Foreign Key ชื่อว่า topic_id ที่เชื่อมอยู่กับ Primary Key ที่ชื่อ id ในตาราง topic เราจะเห็นได้ว่าข้อมูลจำนวนของ comment เราสามารถที่จะทำ subquery ออกมาแสดงผลได้ ยกตัวอย่าง (แบบไม่คิดอะไรมาก) เช่น SELECT *, (SELECT count( * ) FROM comment [...]]]></description>
			<content:encoded><![CDATA[<p>ถ้าว่าตามทฤษฎีฐานข้อมูลแล้วนั้น การ Normalization ตารางเพื่อลดความซ้ำซ้อนของข้อมูล (Redundancy) เป็นสิ่งที่จำเป็นมาก แต่ในการใช้งานจริง การ Normalization ที่มากเกินไป อาจจะก่อผลเสียได้ ยกตัวอย่างเช่น หน้าแสดงกระทู้ในเว็บบอร์ด X จะแสดงข้อมูลจำนวน comment ที่สมาชิกเข้ามาตอบในหัวข้อนั้น ๆ ถ้าเราทำ Normalization ตารางของเว็บบอร์ดตามทฤษฎี โดยให้ตารางที่เก็บความคิดเห็น (comment) แยกจากกระทู้ (topic) ในตาราง comment มี Foreign Key ชื่อว่า topic_id ที่เชื่อมอยู่กับ Primary Key ที่ชื่อ id ในตาราง topic เราจะเห็นได้ว่าข้อมูลจำนวนของ comment เราสามารถที่จะทำ subquery ออกมาแสดงผลได้ ยกตัวอย่าง (แบบไม่คิดอะไรมาก) เช่น</p>
<pre name="code" class="sql">
SELECT  *, (</code>SELECT count(  *  ) FROM comment WHERE topic_id = t.id) rcount FROM  `topic` t
</pre>
<p><span id="more-324"></span>ทีนี้ข้อเสียมันอยู่ตรงไหน? ถ้ายังไม่เห็น ลองสังเกตดี ๆ อีกทีครับ ใครยังนึกไม่ออก ผมจะยกตัวอย่างที่ทำให้เห็นชัดเจนมากขึ้น สมมติว่า แต่ละกระทู้ มีคนตอบกระทู้โดยเฉลี่ยกระทู้ละ 50 comment คำสั่ง COUNT มันก็จะไปนั่งนับจนครบ 50 comment โดย filter ตาม t.id ที่กำหนดแต่ถ้ามีมากกว่านี้ล่ะ เว็บไซต์ดัง ๆ ฮอต ๆ สมาชิกล้นหลาม คนตอบกระทู้เป็นร้อย ๆ พัน ๆ ล่ะ</p>
<p>จะเห็นได้ว่า &#8220;ทุกครั้ง&#8221; ที่มีคนเปิดหน้าแสดงรายชื่อกระทู้ มันจะต้องไปนั่งนับทุกครั้ง ทั้ง ๆ ที่อาจจะไม่ได้มีใครไปตอบกระทู้เพิ่มเลยก็ได้ สิ่งที่เราได้กลับมาจากการทำ Normalization ในครั้งนี้คือ การสิ้นเปลือง CPU สุด ๆ นั่นเอง เรามาหาทางแก้ปัญหากันดีกว่า</p>
<p>วิธีแก้ปัญหาแบบหนึ่งที่ผมจะพูดถึงในครั้งนี้คือการทำ cache ผมไม่ได้หมายถึงการทำ file cache หรือ memory cache นะ แต่ผมหมายถึงการ cache ลงไปในฟิลด์ในตารางครับ</p>
<p>พูดให้ชัดเจนอีกนิดคือ ผมหมายถึงการเพิ่มความซ้ำซ้อนของข้อมูลลงไปอีกนิด เพื่อชีวิตที่ดีกว่า โดยการเพิ่มฟิลด์ชื่อ comment_count ลงไปในตาราง topic และทุกครั้งที่มีการตอบกระทู้ หรือลบ comment ผมก็แค่มาอัพเดทฟิลด์นี้ด้วยเท่านั้นเอง</p>
<pre name="code" class="sql">
UPDATE topic SET comment_count = (SELECT COUNT(*) comment_count FROM comment WHERE topic_id = t.id)
</pre>
<p>ด้วย SQL Statement ข้างบนนี้ มันก็จะไป sync ข้อมูลจำนวนนับจากตาราง comment มาลงในตาราง topic ให้ผม และทุกครั้งที่แสดงหน้ากระทู้ ผมก็เอา comment_count ไปใช้แทน subquery ได้เลย สบายจริง ๆ ครับ</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fblog.chonla.com%2F2011%2F06%2Fsync-%25e0%25b8%2582%25e0%25b9%2589%25e0%25b8%25ad%25e0%25b8%25a1%25e0%25b8%25b9%25e0%25b8%25a5%25e0%25b8%2588%25e0%25b8%25b3%25e0%25b8%2599%25e0%25b8%25a7%25e0%25b8%2599%25e0%25b8%2599%25e0%25b8%25b1%25e0%25b8%259a%25e0%25b8%2588%25e0%25b8%25b2%25e0%25b8%2581%25e0%25b8%2595%25e0%25b8%25b2%25e0%25b8%25a3%25e0%25b8%25b2%2F&amp;title=Sync%20%E0%B8%82%E0%B9%89%E0%B8%AD%E0%B8%A1%E0%B8%B9%E0%B8%A5%E0%B8%88%E0%B8%B3%E0%B8%99%E0%B8%A7%E0%B8%99%E0%B8%99%E0%B8%B1%E0%B8%9A%E0%B8%88%E0%B8%B2%E0%B8%81%E0%B8%95%E0%B8%B2%E0%B8%A3%E0%B8%B2%E0%B8%87%E0%B8%AD%E0%B8%B7%E0%B9%88%E0%B8%99%E0%B8%94%E0%B9%89%E0%B8%A7%E0%B8%A2%20subquery" id="wpa2a_6"><img src="http://blog.chonla.com/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://blog.chonla.com/2011/06/sync-%e0%b8%82%e0%b9%89%e0%b8%ad%e0%b8%a1%e0%b8%b9%e0%b8%a5%e0%b8%88%e0%b8%b3%e0%b8%99%e0%b8%a7%e0%b8%99%e0%b8%99%e0%b8%b1%e0%b8%9a%e0%b8%88%e0%b8%b2%e0%b8%81%e0%b8%95%e0%b8%b2%e0%b8%a3%e0%b8%b2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>เปรียบเทียบ String แบบ Case Sensitive ใน MySQL</title>
		<link>http://blog.chonla.com/2010/04/%e0%b9%80%e0%b8%9b%e0%b8%a3%e0%b8%b5%e0%b8%a2%e0%b8%9a%e0%b9%80%e0%b8%97%e0%b8%b5%e0%b8%a2%e0%b8%9a-string-%e0%b9%81%e0%b8%9a%e0%b8%9a-case-sensitive-%e0%b9%83%e0%b8%99-mysql/</link>
		<comments>http://blog.chonla.com/2010/04/%e0%b9%80%e0%b8%9b%e0%b8%a3%e0%b8%b5%e0%b8%a2%e0%b8%9a%e0%b9%80%e0%b8%97%e0%b8%b5%e0%b8%a2%e0%b8%9a-string-%e0%b9%81%e0%b8%9a%e0%b8%9a-case-sensitive-%e0%b9%83%e0%b8%99-mysql/#comments</comments>
		<pubDate>Thu, 22 Apr 2010 16:31:42 +0000</pubDate>
		<dc:creator>chonla</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Case-Sensitivity]]></category>
		<category><![CDATA[Comparison]]></category>
		<category><![CDATA[String]]></category>

		<guid isPermaLink="false">http://blog.chonla.com/?p=285</guid>
		<description><![CDATA[โดยปกติแล้วการเปรียบเทียบข้อความ (string comparison) ใน MySQL จะเป็นการเปรียบเทียบแบบ Case-Insensitive นั่นคือ ไม่สนใจตัวเล็กตัวใหญ่ หมายถึงว่า &#8220;cat&#8221; จะเท่ากับ &#8220;CAT&#8221; นั่นเอง ปัญหานี้จะพบเมื่อเราทำการเปรียบเทียบ String ที่เป็น Text ในบางครั้ง เราจำเป็นต้องเปรียบเทียบ string แบบ Case-Sensitive เช่น การค้นหา Key ที่ case ของตัวอักษรมีความสำคัญ เราสามารถทำได้หลายวิธี แบบแรกคือ การเปรียบเทียบด้วย Binary String เช่น mysql&#62; SET @s = BINARY 'MySQL'; mysql&#62; SELECT @s = 'mysql'; +--------------+ &#124; @s = 'mysql' &#124; +--------------+ &#124; 0 [...]]]></description>
			<content:encoded><![CDATA[<p>โดยปกติแล้วการเปรียบเทียบข้อความ (string comparison) ใน MySQL จะเป็นการเปรียบเทียบแบบ Case-Insensitive นั่นคือ ไม่สนใจตัวเล็กตัวใหญ่ หมายถึงว่า &#8220;cat&#8221; จะเท่ากับ &#8220;CAT&#8221; นั่นเอง ปัญหานี้จะพบเมื่อเราทำการเปรียบเทียบ String ที่เป็น Text ในบางครั้ง เราจำเป็นต้องเปรียบเทียบ string แบบ Case-Sensitive เช่น การค้นหา Key ที่ case ของตัวอักษรมีความสำคัญ เราสามารถทำได้หลายวิธี</p>
<p><span id="more-285"></span></p>
<p>แบบแรกคือ การเปรียบเทียบด้วย Binary String เช่น</p>
<pre>mysql&gt; <strong><code>SET @s = BINARY 'MySQL';</code></strong>
mysql&gt; <strong><code>SELECT @s = 'mysql';</code></strong></pre>
<pre>+--------------+
| @s = 'mysql' |
+--------------+
|            0 |
+--------------+</pre>
<p>แบบที่สองคือ การสั่งเปลี่ยน COLLATE ให้เป็นแบบที่สนับสนุนการเปรียบเทียบแบบ case-sensitive นั่นคือ latin1_bin หรือ latin1_general_cs เช่น</p>
<pre>mysql&gt; <strong><code>SET @s1 = 'MySQL' COLLATE latin1_bin,</code></strong>
    -&gt; <strong><code>    @s2 = 'mysql' COLLATE latin1_bin;</code></strong>
mysql&gt; <strong><code>SELECT @s1 = @s2;</code></strong>
+-----------+
| @s1 = @s2 |
+-----------+
|         0 |
+-----------+</pre>
<p>แบบที่ 3 ก็เป็นการเปลี่ยน Collation เช่นเดียวกัน แต่เป็นการไปตั้งค่าที่ field ใน table ของเราเลยครับ แค่เพียงเลือก field ที่ต้องการ และเปลี่ยน collation ให้เป็น latin1_bin หรือ latin1_general_cs ก็ใช้ได้แล้วครับ</p>
<p><strong>อ้างอิง</strong></p>
<ul>
<li><a href="http://dev.mysql.com/doc/refman/5.0/en/case-sensitivity.html">http://dev.mysql.com/doc/refman/5.0/en/case-sensitivity.html</a></li>
</ul>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fblog.chonla.com%2F2010%2F04%2F%25e0%25b9%2580%25e0%25b8%259b%25e0%25b8%25a3%25e0%25b8%25b5%25e0%25b8%25a2%25e0%25b8%259a%25e0%25b9%2580%25e0%25b8%2597%25e0%25b8%25b5%25e0%25b8%25a2%25e0%25b8%259a-string-%25e0%25b9%2581%25e0%25b8%259a%25e0%25b8%259a-case-sensitive-%25e0%25b9%2583%25e0%25b8%2599-mysql%2F&amp;title=%E0%B9%80%E0%B8%9B%E0%B8%A3%E0%B8%B5%E0%B8%A2%E0%B8%9A%E0%B9%80%E0%B8%97%E0%B8%B5%E0%B8%A2%E0%B8%9A%20String%20%E0%B9%81%E0%B8%9A%E0%B8%9A%20Case%20Sensitive%20%E0%B9%83%E0%B8%99%20MySQL" id="wpa2a_8"><img src="http://blog.chonla.com/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://blog.chonla.com/2010/04/%e0%b9%80%e0%b8%9b%e0%b8%a3%e0%b8%b5%e0%b8%a2%e0%b8%9a%e0%b9%80%e0%b8%97%e0%b8%b5%e0%b8%a2%e0%b8%9a-string-%e0%b9%81%e0%b8%9a%e0%b8%9a-case-sensitive-%e0%b9%83%e0%b8%99-mysql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

