<?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>DominixZ : Live Smart &#38; Geeky &#187; วิธีแก้ปัญหาเขียนโปรแกรม</title> <atom:link href="http://www.dominixz.com/blog/category/programming-solution/feed/" rel="self" type="application/rss+xml" /><link>http://www.dominixz.com/blog</link> <description>Productivity , Techology News ,Website Review , Web Standard , Live Smart and Geeky</description> <lastBuildDate>Wed, 08 Feb 2012 16:59:00 +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>Tuning MySQL : Case Study OBVOC/OBHUNTER</title><link>http://www.dominixz.com/blog/programming-solution/tuning-mysql-case-study-obvoc-obhunter/</link> <comments>http://www.dominixz.com/blog/programming-solution/tuning-mysql-case-study-obvoc-obhunter/#comments</comments> <pubDate>Tue, 13 Sep 2011 15:22:47 +0000</pubDate> <dc:creator>DominixZ</dc:creator> <category><![CDATA[VPS]]></category> <category><![CDATA[วิธีแก้ปัญหาเขียนโปรแกรม]]></category> <category><![CDATA[เคล็คลับซอฟต์แวร์]]></category><guid
isPermaLink="false">http://www.dominixz.com/blog/?p=1409</guid> <description><![CDATA[เนื่องจากผมไม่รู้จะยก Case ไหนดีมาเป็นตัวอย่างการทดลองให้ดู ผมก็เลยยก Case ที่พึงเกิดขึ้นกับตัวสดๆร้อนๆคือการ Tuning MySQL สำหรับระบบ Bot Monitoring บนโลก Online โดยคราวนี้หนักกว่าเดิมคือปกตินั้น Server จะมีแค่ OBVOC กับ Sodia เท่านั้นที่ดูแลแต่วันนี้มันมี OBHUNTER ซึ่งตอนแรกอยู่เครื่องภายในแต่วันนี้มันได้มาอยู่บน Server จริงๆแล้ว อธิบายง่ายๆเหมือนมี Transaction เพิ่มขึ้นมากกว่าเดิม 3 เท่า !! ดังนั้นเรื่องที่ผมจะยกขึ้นมาวันนี้คือเรื่องนี้ครับ โดยสภาพแวดล้อมคร่าวๆมีดังนี้ OS : Centos 5 with DirectAdmin PHP 5.3.8 , MySQL 5.1 Server : CPU 8 Core , Ram 16GB , HDD 250GB ผมโชคดีอย่างหนึ่งที่ได้ [...]]]></description> <content:encoded><![CDATA[<p>เนื่องจากผมไม่รู้จะยก Case ไหนดีมาเป็นตัวอย่างการทดลองให้ดู ผมก็เลยยก Case ที่พึงเกิดขึ้นกับตัวสดๆร้อนๆคือการ Tuning MySQL สำหรับระบบ Bot Monitoring บนโลก Online โดยคราวนี้หนักกว่าเดิมคือปกตินั้น Server จะมีแค่ OBVOC กับ Sodia เท่านั้นที่ดูแลแต่วันนี้มันมี OBHUNTER ซึ่งตอนแรกอยู่เครื่องภายในแต่วันนี้มันได้มาอยู่บน Server จริงๆแล้ว อธิบายง่ายๆเหมือนมี Transaction เพิ่มขึ้นมากกว่าเดิม 3 เท่า !! ดังนั้นเรื่องที่ผมจะยกขึ้นมาวันนี้คือเรื่องนี้ครับ โดยสภาพแวดล้อมคร่าวๆมีดังนี้</p><ul><li>OS : Centos 5 with DirectAdmin</li><li>PHP 5.3.8 , MySQL 5.1</li><li>Server : CPU 8 Core , Ram 16GB , HDD 250GB</li></ul><p>ผมโชคดีอย่างหนึ่งที่ได้ Server ใหม่มา ไม่งั้นไม่มีทางทำสำเร็จได้แน่ในคราวนี้ โดยปัจจัยแรกที่สำคัญสำหรับระบบที่ใหญ่ขึ้นคือ &#8220;Server&#8221; แต่กระนั้น เราจะรู้ได้ไงลองไปอ่าน <a
href="http://www.dominixz.com/blog/programming-solution/8-things-for-young-web-development" target="_blank">โพสนี้</a>ดูนะครับ เสร็จแล้วคราวนี้พอมีเครื่องที่พร้อม แต่เชื่อเถอะว่า ถึงแม้มันจะพร้อมแต่บางครั้งคุณก็ไม่สามารถปรับ Performance ให้สุดได้เพราะ Ram นั้นต่อให้มี 128GB ถ้าเรา config มั่วๆก็หมดได้อยู่ดีครับ ลองดู Case ผมเป็นตัวอย่างแล้วกันครับ โดยผมจะบอกเรื่องราวก่อนและหลัง แล้วตอนท้ายไปชม Video กันนะครับ</p><p><strong>ก่อนหน้านี้ที่มี OBVOC ตัวเดียว</strong></p><ul><li>มีการอัพเดต Row ที่ขนาด 10kb ขึ้นไปเพราะเป็นการดูดกระทู้ เช่น Pantip , Sanook  เข้าระบบ</li><li>ใช้ MyISAM Fulltext เพราะ Implement ได้ง่ายกว่า Sphinx , Solr แต่ปัญหาคือ Index จำนวนมาก</li><li>ข้อมูลเริ่มเต็ม Table เดียวก็ 16gb แล้ว</li><li>ถึงแม้จะ insert / update บ่อยแต่ก็ยังรับไว้ในเครื่อง ram 3gb</li><li>เวลาจะดู Dashboard ในหน้า OBVOC บางครั้งใช้เวลาถึง 30-60 วินาที</li></ul><p><strong>หลังมี OBVOC และ OBHUNTER ร่วมกัน</strong></p><ul><li>Transaction มากกว่าเดิม 3 เท่า</li><li>มีการ Access Disk มากกว่าเดิมมากๆ เพราะ OBHUNTER เป็นการอัพเดตข้อมูลไม่เล็กไม่ใหญ่ แต่ถี่ๆ เช่นตัด comment จาก pantip ออกมา insert</li><li>Table ที่โตวันโตคืนเป็นคู่แข่ง table ของ obvoc ทำให้ไฟล์ใหญ่ขึ้นมาก</li><li>OBHUNTER ได้ใช้สถาปัตยกรรมคล้ายๆกับ OBVOC ก็คือใช้ Fulltext ซึ่งปัญหาคือ Index มันมากๆๆๆ กว่าเดิมเข้าไปอีก</li><li>ระบบทั้งหมดช้าลง แล้วเกิดอาการ Hang เพราะมีการ Access Disk เยอะจนไม่สามารถแม้กระทั่งเข้า FTP/SSH (Write Access 99%)</li><li>บางครั้งต้อง Repair พร้อมกับเปิด Service เพราะกลัวเรื่องข้อมูลเก็บได้ไม่หมดจากบน Social Media</li></ul><p><strong>ปัญหาที่เกิดระหว่างการ Tuning</strong></p><ul><li>ลองผิดลองถูก ทำให้บางครั้งการแก้ปัญหาไม่ถูกจุดทำให้ระบบแย่กว่าเดิมต้อง Restart VM กันเลย</li><li>เจอ Bug ที่ประหลาดมากนั้นคือ &#8220;Crond&#8221; เกิดขึ้นมาเป็นจำนวนมากกว่า &gt; 1000 เคยหลับไปแล้วตื่นขึ้นมา ram 16gb เต็ม งงกันไปเลย</li><li>Table ขนาด 16gb พังแค่กด stop start mysql ! ได้บทเรียนว่าก่อน start stop ควร kill ทุก process ที่เข้ามาใน db ไม่งั้นมีโอกาสพัง confirm !! (โดยพี่ @icez บอกเพิ่มอีกนิดว่าอาจจะเป็น Distro ของผมที่ใช้ Centos with DirectAdmin ทำให้มันรวนได้ง่ายขนาดนี้ ดังนั้นใครลง Distro แนะนำว่าลงเองดีกว่า !! ถ้าคิดการใหญ่)</li><li>การ Repair Table แบบผิดวิธีคือ เข้าใจผิดว่า Repairing by Keycache นั้นเร็วกว่า Repairing by Sorting จริงๆผิดครับ Sorting เร็วกว่า แล้วถ้าจะให้ดีต้องมี Thread ด้วย ดังนั้นก่อน Repair ควรปรับ config key_buffer_size=2048M sort_buffer_size=2048M read_buffer_size 512 แล้วก็ write_buffer_size 512 ไม่งั้นช้ามาก + ผลพวงที่ไม่ทำแบบนี้อาจทำให้เกิด Write Access 99% ทำให้ server พังเดี้ยงได้ อาจะเพิ่มเติมได้ที่ <a
href="http://venublog.com/2010/01/04/performance-comparison-of-repair-by-sorting-or-by-keycache/" target="_blank">ลิงค์นี้</a></li><li>ระหว่าง config มั่วๆถ้าไม่ set connection timeout แล้วละก็ ram จะหมดรวดเร็วอย่างไม่รู้ตัว (ของผมหมดเร็วเห็นได้ชัดเพราะบอทมันกระหน่ำเข้ามา) โดยตอนนี้ ผมเลยปรับ config เป็นแบบนี้เลย interactive_timeout=100 , wait_timeout=100 ,connect_timeout=10</li><li>การปรับ Tuning MySQL ไม่ดีดูง่ายๆ ถ้าปิด MySQL แล้วระบบมีการ Write Access เท่าไร แล้วเมื่อเปิด MySQL เท่าไร ถ้าเลขมันมากหลังเปิด MySQL นั้นและชัดเจน !</li><li>ถ้ายังอยากใช้ MySQL ต่อไปต้องเข้าใจ InnoDB กับ MySQL โดยผมเจอปัญหาหนึ่งที่แก้เท่าไรก็ไม่ได้สุดท้ายเลยต้องเปลี่ยน Storage Engine ถึงบรรเท่าปัญหานี้ได้</li><li>low_priority_updates = 1 นี้คือท่าสุดท้าย สำหรับคนใช้ MyISAM ถ้าแก้ปัญหาไม่ได้สักที ลองเปลี่ยน config นี้ดูครับ โดยเป็นการให้ความสำคัญกับ UPDATE SQL น้อยลงครับ โดยปกติแล้ว UPDATE จะสำคัญกว่า SELECT ที่มันน่าเซ็งก็คือ ถ้า UPDATE มาแล้วมี SELECT ตาม UPDATE จะช้าลงครับ (มันคือเรื่องจริงครับลองมาเยอะแล้วสำหรับ MyISAM) โดยถ้าปกติมีอย่างใดอย่างหนึ่งจะเร็วทั้งคู่แต่ถ้ามาพร้อมกันเมื่อไร ช้าเลย Lock ด้วย ผมเลยแก้ปัญหาคือให้ SELECT ไปก่อน เพราะถ้าเรา Tuning ดีแล้ว SELECT จะเร็วปรี๊ดแล้วระบบก็จะได้เอาเวลาไปทำ UPDATE ได้เร็วกว่าเดิม ลองแล้ว confirm ว่าเร็วกว่าให้มันเป็นแบบปกติใน Table MyISAM แต่มีผลเสียคือ <strong>&#8220;บางครั้ง User กด Update ไปแล้ว แต่มันไม่ได้ทำงานทันที เลยเห็นเป็นข้อมูลเก่าอยู่ๆทั้งที่ส่ง request ไปแล้ว&#8221;</strong></li><li>Log คือศัตรูตัวฉกาจสำหรับระบบที่มีการ Insert/Update เยอะๆ เพราะมันคืออีก 1 ตัวที่ทำให้เกิด Write Access ว่ากระนั้นผมเลยปิด Log หมดเลย (แต่ปิดตอนที่เริ่ม Tuning เริ่มดีแล้วนะ ไม่ใช่ปิดแต่เริ่ม) ผมปิดหมดเลยครับทั้ง log-queries-not-using-indexes , log , log-slow-queries , log_error , log_warnings ปิดหมด แต่ตัวที่ห้ามปิดเด็ดขาดคือ log_bin เพราะเจ้านี้สำคัญมากเวลาจะกู้ข้อมูลจากการ Repair ดังนั้นอย่าปิดยอมๆไป</li><li>MySQL.. ERROR! Manager of pid-file quit without updating file. เวลา restart mysql นั้นส่วนใหญ่มาจากเขียน config ซะมากกว่า pid ตัวนั้นค้างอยู่ในระบบ</li><li>Read Buffer Size เป็นตัวเดียวที่ใส่เป็นแค่ 8MB ก็เพียงพอแล้ว ที่เหลือต้องแล้วแต่ระบบ</li><li>การทำ Index เยอะใช่ว่าจะดี เพราะมันคือการเพิ่ม Write Access !!!! ดังนั้นถ้าตัวไหนไม่ค่อยได้ใช้ให้ Remove Index ทิ้งซะ ผมดันสร้างตัวทำ autoindex มันเลยทำ index ให้ทุก field เลยผลที่ได้ช่วงแรกคือเร็ว แต่พอระบบใหญ่ก็เป็นดังที่เห็น &gt;.&lt;&#8217;</li><li>หลงผิดเชื่อในค่าตัวเลข ที่ฝรั่งแนะนำว่าอย่าเกินเท่านี้นะ มันจะมีผลต่อ Performance Issue ทำให้เราไม่กล้าปรับ จนสุดท้ายมันก็ต้องปรับ แล้วมันก็ดีขึ้นจริงๆด้วย !!</li><li>กด Repair Table ไปแล้ว Bug Crond มันเกิดขึ้น ไม่มีหน้าจอที่เข้า SSH ไว้สุดท้ายเลยต้องมานั่ง Kill มือเพราะมันเกิดตอนจังหวะ Repair Table ไปแล้ว 3 ชั่วโมง !! + ทำใหม่มาหลายรอบเลยใช้ DirectAdmin ช่วยแล้วก็ใช้ jQuerify ของ Firefox เข้าช่วยโดย login เป็น root แล้วเปิดไปหน้าที่มี crond เยอะๆแล้วพิมพ์ตัวนี้ลงไปใน firebug console &#8220;$(&#8220;tr td.list:contains(&#8216;crond&#8217;)&#8221;).each(function(){ $(&#8220;input&#8221;,$(this).parent()).attr(&#8220;checked&#8221;,true) });$(&#8220;tr td.list2:contains(&#8216;crond&#8217;)&#8221;).each(function(){ $(&#8220;input&#8221;,$(this).parent()).attr(&#8220;checked&#8221;,true) });&#8221; เสร็จแล้วคลิก kill แล้วกดลบ</li><li>Optimize Table ทำให้เร็วขึ้นมหาศาลอย่างเห็นได้ชัด แต่ถ้ายัง Tuning ไม่นิ่งก็อย่าพึง Optimize เลยเพราะถ้า Alter หรือ Repair ก็ต้องกดใหม่อยู่ดี</li></ul><p><strong>ความโชคดีที่ผมหาความต้องการของระบบผมเจอ</strong></p><ul><li>ระบบผมมีคนใช้แค่ 10-20 คนเท่านั้น ที่เหลือเป็นบอท ทำให้ Max Connection สามารถปรับลดลงได้</li><li>ผมมี Key Size ทั้งหมด 6.8GB โดยผมลองปรับเรื่อยๆจนมาลงตัวที่ 3GB ซึ่งคลอบคลุม 95% ของระบบแล้ว ซึ่งพอแล้วเอา Ram ไปเพิ่มตัวอื่น</li><li>ผมรู้ว่าระบบผมมีการ JOIN และ SORT บ่อยมาก ผมเลยค่อยๆเพิ่มค่า Buffer และ Test จนลงตัว</li><li>Coding บางส่วนมีผลต่อ Performance ของระบบมาก โชคดีที่ผมเขียนมันขึ้นมาเองเลยจำได้ว่าอยู่ส่วนไหน เลยแก้ได้ถูกจุด</li></ul><p>บทสรุปของการ Tuning ในครั้งนี้ คือเราต้องคอย Monitor ตัวเลขต่างๆ ค่อยๆปรับทีละนิดละนิด โดยแต่ละครั้งที่จะ stop อย่าลืม kill ตัวที่มันมา access database ก่อน แล้วคอยใช้คำสั่ง top ของ linux ดูด้วยว่า write access ลดลงแล้วหรือยังกับการ insert/update ปริมาณเดิม ถ้าไม่ลดต้องปรับใหม่ โดยอย่าให้มัน Write Access ทุก Core เยอะกว่า 30% (แต่ถ้ามัน 99% ไม่เกินครึ่งหนึ่งของจำนวน CPU core ก็ปล่อยๆมันไปได้) สุดท้ายท้ายสุดก็คืออย่าใช้ทั้ง Server เกิน 60-70% ของ RAM (ต้องลอง run สัก 24 ชั่วโมงด้วย) เพราะถ้าเหลือพื้นที่ RAM ไว้น้อยกว่านี้เมื่อเกิดมี process ตัวใดเกิดขึ้นแล้วกิน ram เราไปจนหมด เราเข้า SSH/FTP แถม Write Access 99% ผลสุดท้ายคือต้องโทรไปบอกทาง Server ว่ากด Restart ที่เครื่องให้หน่อย ทำให้เกิดความล่าช้าในการ Tuning แถมระบบก็ล่มหมดอีกคราวนี้ ไม่คุ้มกันนะ ที่เหลือก่อนไปชม video ด้านล่างกันผมขอพูดคำๆหนึ่งเลยว่า</p><blockquote><p
style="text-align: center;">Tuning ต้องวิเคราะห์และค่อยๆปรับไปทีละนิด ความเชื่อที่เรา Search จาก Internet บางครั้งก็ไม่จริงเสมอไป เราต้องทดลองทำด้วยตัวเอง เพราะปัญหาของเรา บางทีไม่ใช่ปัญหาที่เขาเคยเจอ</p></blockquote><p><span
style="color: #ff0000;">ข้อควรจำ : อย่าใช้ RAM เกิน 70% โดยไม่จำเป็น , อย่าให้เกิด Write Access มากๆเป็นเวลานาน</span></p><p><a
href="http://dominixz.com/blog/files/first_obvoc_my.cnf.txt" target="_blank">My.cnf ที่ Tuning ในครั้งแรกของ OBVOC</a><br
/> <a
href="http://dominixz.com/blog/files/my.cnf_16GB.txt" target="_blank">My.cnf ที่ลองใช้ตาม Internet แต่ไม่ได้ผลใน case นี้</a><br
/> <a
title="OBVOC OBHUNTER MySQL Config for frequency insert/update text field" href="http://dominixz.com/blog/files/obsa_sep_2011_my.cnf.txt" target="_blank">My.cnf ตัวสุดท้ายที่ใช้อยู่​ณ ปัจจุบันนี้</a></p> Similar Posts:<ul><li><a
href="http://www.dominixz.com/blog/programming-solution/tuning-mysql-trace-yourself-and-understand-variable/" rel="bookmark" title="September 11, 2011">Tuning MySQL : สำรวจตัวเองและเข้าใจตัวแปร</a></li><li><a
href="http://www.dominixz.com/blog/programming-solution/8-things-for-young-web-development/" rel="bookmark" title="August 15, 2011">ประสบการณ์ 8 ข้อที่อยากให้เด็กรุ่นใหม่รู้กับการทำ Web Development</a></li><li><a
href="http://www.dominixz.com/blog/geek-tips/increase-speed-mysql-fulltext-order-by-with-this-mindset/" rel="bookmark" title="May 5, 2011">วิธี Search MySQL ด้วย Fulltext Order By Query เร็วและแรง</a></li></ul>]]></content:encoded> <wfw:commentRss>http://www.dominixz.com/blog/programming-solution/tuning-mysql-case-study-obvoc-obhunter/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Tuning MySQL : สำรวจตัวเองและเข้าใจตัวแปร</title><link>http://www.dominixz.com/blog/programming-solution/tuning-mysql-trace-yourself-and-understand-variable/</link> <comments>http://www.dominixz.com/blog/programming-solution/tuning-mysql-trace-yourself-and-understand-variable/#comments</comments> <pubDate>Sun, 11 Sep 2011 02:47:04 +0000</pubDate> <dc:creator>DominixZ</dc:creator> <category><![CDATA[VPS]]></category> <category><![CDATA[วิธีแก้ปัญหาเขียนโปรแกรม]]></category> <category><![CDATA[เคล็คลับซอฟต์แวร์]]></category><guid
isPermaLink="false">http://www.dominixz.com/blog/?p=1407</guid> <description><![CDATA[เนื่องจากว่าอาทิตย์ที่ผ่านมาผมคลุกคลีอยู่กับการปรับปรุงประสิทธิภาพของ MySQL ซึ่งการทำครั้งนี้ก็ประสบความสำเร็จไปได้ดี โดยผมตั้งใจจะนำความรู้มาให้กับ คนรุ่นใหม่ที่คิดการใหญ่ แต่ติดปัญหา Database ช้ารองรับคนเข้าไม่ได้เยอะ หรือเจอปัญหาเฉพาะทางอย่างของผมที่มีการอัพเดตอยู่ตลอดเวลา Table บวม 16gb ทำยังไงให้มันเร็วได้บ้าง โดยวันนี้ผมขอ Scope เฉพาะเรื่องการค้นหาปัญหาก่อน ที่จะ Tuning ดังนั้น ถึงแม้เราจะมีเครื่องที่มีประสิทธิภาพแค่ไหน แต่ถ้าเราไม่รู้สาเหตุที่แท้จริงก็ทำให้เร็วขึ้นไม่ได้ เครื่องมือสำคัญมีดังนี้ phpMyAdmin MySQLTuner MySQL Tuning Primer Optimize only fragmented tables in MySQL โดย 2 ตัวล่างเราต้องมี SSH เพื่อเข้าไปสั่งมันรันด้วย perl กับ sh ได้นะครับ โดยวิธีใช้ก็เรียกชื่อไฟล์นั้นตรงๆ (ข้ออนุญาติไม่สอนแต่มันไม่ยากเลยนะ ) เสร็จแล้วเราจะเจออะไรทำนองแบบใน ลิงค์นี้ ทีนี้เราต้องทำความเข้าใจว่าทำไม Query เราช้าเป็นเพราะอะไร ดังนั้นก่อนจะสำรวจตัวเองคุณต้องเข้าใจเรื่องหลักๆของ MySQL หรือ RDBMS ทั่วไปและ [...]]]></description> <content:encoded><![CDATA[<p>เนื่องจากว่าอาทิตย์ที่ผ่านมาผมคลุกคลีอยู่กับการปรับปรุงประสิทธิภาพของ MySQL ซึ่งการทำครั้งนี้ก็ประสบความสำเร็จไปได้ดี โดยผมตั้งใจจะนำความรู้มาให้กับ คนรุ่นใหม่ที่คิดการใหญ่ แต่ติดปัญหา Database ช้ารองรับคนเข้าไม่ได้เยอะ หรือเจอปัญหาเฉพาะทางอย่างของผมที่มีการอัพเดตอยู่ตลอดเวลา Table บวม 16gb ทำยังไงให้มันเร็วได้บ้าง โดยวันนี้ผมขอ Scope เฉพาะเรื่องการค้นหาปัญหาก่อน ที่จะ Tuning ดังนั้น ถึงแม้เราจะมีเครื่องที่มีประสิทธิภาพแค่ไหน แต่ถ้าเราไม่รู้สาเหตุที่แท้จริงก็ทำให้เร็วขึ้นไม่ได้ เครื่องมือสำคัญมีดังนี้</p><ul><li>phpMyAdmin</li><li><a
title="MySQL Tuner " href="http://mysqltuner.pl/mysqltuner.pl" target="_blank">MySQLTuner</a></li><li><a
title="MySQL Performance Tuning Primer" href="http://www.day32.com/MySQL/tuning-primer.sh" target="_blank">MySQL Tuning Primer</a></li><li><a
href="http://meinit.nl/optimize-only-fragmented-tables-mysql">Optimize only fragmented tables in MySQL </a></li></ul><p>โดย 2 ตัวล่างเราต้องมี SSH เพื่อเข้าไปสั่งมันรันด้วย perl กับ sh ได้นะครับ โดยวิธีใช้ก็เรียกชื่อไฟล์นั้นตรงๆ (ข้ออนุญาติไม่สอนแต่มันไม่ยากเลยนะ <img
src='http://www.dominixz.com/blog/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> ) เสร็จแล้วเราจะเจออะไรทำนองแบบใน <a
href="http://www.unix.com/web-programming/75618-mysql-tuning-tools-mysqltuner-pl-tuning-primer-sh.html" target="_blank">ลิงค์นี้</a> ทีนี้เราต้องทำความเข้าใจว่าทำไม Query เราช้าเป็นเพราะอะไร ดังนั้นก่อนจะสำรวจตัวเองคุณต้องเข้าใจเรื่องหลักๆของ MySQL หรือ RDBMS ทั่วไปและ Server กันก่อน ผมจะขอรวบรัดใครอยากรู้ลึกๆไปศึกษากันต่อนะครับ</p><ul><li>เวลาเรา Query ข้อมูลปกตินั้นก็เหมือนเรามีกองเอกสารที่ไม่ได้มีการจัดเรียงวางกองๆไว้ เวลาจะหาเราก็เลยต้องรื้อถึงจะเจอ ทำให้ไม่มีประสิทธิภาพ</li><li>ถ้าเรานำเอกสารมาเรียงๆก็สามารถถูกหาได้ง่ายขึ้นกว่ากองเอกสารมั่วๆ สิ่งนี้ใน MySQL เรียกว่า <strong>&#8220;Optimize Table&#8221; </strong>โดย Script ที่ผมนำมาใช้คือ Optimize เฉพาะ Fragment หรืออันที่ไม่ได้มีการเรียงข้อมูล ซึ่งเราจะพบได้ง่ายมากใน Table ขนาดใหญ่ ยังไงก็ระวังกันนิดหนึ่งคือถ้าไป Optimize Table ใหญ่ก็เสียเวลาหน้าดู<strong><br
/> </strong></li><li>ต่อให้เรียงแล้วแต่ถ้าเราอยากจะหาเอกสาร ABC ได้ง่ายขึ้นเราก็จะแปะ PostIt สีๆให้ออกมาข้างๆหรือใส่ที่คั่นหนังสือใน DB เราเรียกว่า <strong>&#8220;Index&#8221;</strong></li><li>แต่การจะหยิบข้อมูลเอกสารพร้อมๆกันหลายๆอันได้นั้นจะต้องมีความจำที่เพียงพอว่าแต่ละเอกสารนั้นอยู่ที่ไหน (Index อยู่ไหน) ทำให้ต้องใช้ความจำเข้ามา แล้วถ้าเราจำที่อยู่ของแต่ละเอกสารนั้นไม่ได้ เราก็ต้องค่อยๆเปิดทีละกองสองกอง (Key Buffer &lt; Key Index ) ทำให้ช้าลง</li><li>อีกเรื่องที่ทำให้ช้าได้คือ <strong>&#8220;พื้นที่โต๊ะไม่พอ&#8221;</strong> เหมือนกองเอกสารที่เราเก็บใส่แฟ้มแล้วไปว่างไว้ที่อื่น แต่ไม่ใช่บนโต๊ะเวลาจะนำมาใช้ก็ต้องเดินไปหยิบ ดังนั้นถ้าโต๊ะเราสามารถเก็บกองเอกสารทั้งหมดได้ เราก็ไม่ต้องเดินไปหยิบพอเต็มก็ทำให้เสร็จ แล้วก็เดินไปหยิบใหม่ นั้นเป็นที่มาของ <strong>&#8220;tmp_table_size&#8221;</strong></li><li>ส่วนตัวแปรอื่นๆที่มีผลในการทำเอกสารนั้นประกอบด้วย การอ่านเอกสาร (read_buffer_size) , การเรียงเอกสาร (sort_buffer_size) , การรวมเอกสาร (join_buffer_size) และการอ่านเอกสารที่สุ่มมา (<a
href="http://www.mysqlperformanceblog.com/2007/07/24/what-exactly-is-read_rnd_buffer_size/" target="_blank">read_rnd_buffer_size</a>) โดยอันสุดท้ายมักจะเยอะขึ้นถ้ามีการ ORDER BY เยอะๆ</li><li>สุดท้ายการจะทำงานได้เร็วคุณต้องทำงานเป็นทีมดังนั้น อย่าลืมจ้างพนักงานเพิ่ม​โดยต้องจ่ายเป็นเงินเดือน (CPU/Mem) โดยพนักงานมีชื่อเรียกใน DB ว่า (thread_concurrency) ถ้าเราอยากให้ผู้ช่วยเก่งๆ ก็ต้องฝึก การอ่านเอกสาร (read_buffer_size) , การเรียงเอกสาร (sort_buffer_size) , การรวมเอกสาร (join_buffer_size) และการอ่านเอกสารที่สุ่มมา (<a
href="http://www.mysqlperformanceblog.com/2007/07/24/what-exactly-is-read_rnd_buffer_size/" target="_blank">read_rnd_buffer_size</a>) ซึ่งยิ่งพนักงานเก่งก็ต้องยิ่งจ่ายแพง (จ่ายแพงโดยเฉพาะ Memory)</li></ul><p>หลักๆการ Tuning MySQL ก็จะมีเรื่องประมาณนี้ครับ โดยเราไปดูวิธีตรวจสอบว่าส่วนไหนของระบบเราช้ากันครับ โดยจะเป็นภาษาเทคนิค ถ้าฟังไม่เข้าใจก็ขออภัยนะครับ &gt;.&lt;</p><p
style="text-align: center;"><iframe
width="560" height="345" src="http://www.youtube.com/embed/HGbjnhvkSVI" frameborder="0" allowfullscreen></iframe></p><p
style="text-align: left;">จบไปแล้วกับการอธิบายวิธีดูว่าส่วนไหนช้าและตัวแปรแต่ละตัวใน my.cnf เอาไว้ทำอะไร โดยผมเอาต้นแบบ config มาจาก <a
href="http://datastrangler.com/windpipe/2011/02/24/custom-mysql-config-files-to-ensure-maximum-performance/" target="_blank">Custom MySQL for ensure maximum performance</a> ครับ โดยเท่าที่ลองดู Config แล้วมันเหมาะสำหรับเว็บทั่วไป , Blog , Webboard อะไรทำนองนี้ซึ่งข้อมูลแต่ละ Row ไม่ได้มีขนาดใหญ่มาก และไม่ได้ใช้ Fulltext แล้วเน้นไปที่มีคนเข้ามาใช้จำนวนมาก ซึ่ง Config ที่เขาให้มาถือว่าดีแล้ว แต่จะเหมาะกับเราหรือไม่ต้องตรวจสอบดูกันเองนะครับ</p> Similar Posts:<ul><li><a
href="http://www.dominixz.com/blog/programming-solution/tuning-mysql-case-study-obvoc-obhunter/" rel="bookmark" title="September 13, 2011">Tuning MySQL : Case Study OBVOC/OBHUNTER</a></li><li><a
href="http://www.dominixz.com/blog/geek-tips/increase-speed-mysql-fulltext-order-by-with-this-mindset/" rel="bookmark" title="May 5, 2011">วิธี Search MySQL ด้วย Fulltext Order By Query เร็วและแรง</a></li><li><a
href="http://www.dominixz.com/blog/programming-solution/8-things-for-young-web-development/" rel="bookmark" title="August 15, 2011">ประสบการณ์ 8 ข้อที่อยากให้เด็กรุ่นใหม่รู้กับการทำ Web Development</a></li></ul>]]></content:encoded> <wfw:commentRss>http://www.dominixz.com/blog/programming-solution/tuning-mysql-trace-yourself-and-understand-variable/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>ประสบการณ์ 8 ข้อที่อยากให้เด็กรุ่นใหม่รู้กับการทำ Web Development</title><link>http://www.dominixz.com/blog/programming-solution/8-things-for-young-web-development/</link> <comments>http://www.dominixz.com/blog/programming-solution/8-things-for-young-web-development/#comments</comments> <pubDate>Mon, 15 Aug 2011 16:44:49 +0000</pubDate> <dc:creator>DominixZ</dc:creator> <category><![CDATA[VPS]]></category> <category><![CDATA[วิธีแก้ปัญหาเขียนโปรแกรม]]></category> <category><![CDATA[เคล็คลับซอฟต์แวร์]]></category><guid
isPermaLink="false">http://www.dominixz.com/blog/?p=1377</guid> <description><![CDATA[ถึงวันนี้ก็เป็นเวลาหลายปีแล้วที่ผมได้มาจับด้านเว็บเป็นอาชีพจริงๆนับย้อนไปตั้งแต่ปี 2 จนมาถึงตอนนี้ปี 2011 ก็เป็นเวลา 5 ปีแล้วที่ได้ทำอาชีพนี้ โดยต้องบอกก่อน ว่าผมไม่เคยได้จับระบบใหญ่ ไม่เคยเจองานที่ Hit Limit ของสถาปัตยกรรม จนกระทั่งมาทำงานๆหนึ่งที่เรียกว่า &#8220;บอทเว็บ&#8221; แน่นอน OBVOC ไม่ใช่งานบอทเว็บ ตัวแรกของผม แล้วแต่ละตัวก็ไม่เคยเจอ Limit จนกระทั่งเอามาใช้งานจริง ทำแบบ Commercial จริงๆ แล้วทำให้รู้ว่าจริงๆ สิ่งที่เราคิดว่าดีตอนแรกมันอาจไม่ดีถึงตอนหลังก็ได้ เลยอยากจะมาถ่ายทอดความรู้กับนักพัฒนาหรือใครก็ตามที่ กำลังจะทำเว็บขนาดใหญ่หรือมี Transaction สูงๆแล้วก็เป็นสาเหตุว่าทำไมผมถึงต้องพัฒนาก้าวไปอีกขั้นด้วยเทคโนโลยีที่พึงมาในปัจจุบัน โดยสาเหตุที่เจอมากับตัวก็คือ เงินทุนที่่มีอย่างจำกัดทำให้เรามี Server ขนาดเล็กกว่าที่ Application เราต้องการสมมุติว่าคุณมี RAM อยู่ 1GB แล้วเป็น Shared CPU แต่คุณต้องการทำ Fulltext , การวิเคราะห์และคำนวณเพื่อนำมาทำสถิติ ซึ่งใช้ CPU 100% เกือบตลอดเวลา ดังนั้นปัญหาแรกคือ &#8220;ทรัพยากร&#8221; อย่ามีน้อยเกินไปกับขนาดตัว App [...]]]></description> <content:encoded><![CDATA[<p>ถึงวันนี้ก็เป็นเวลาหลายปีแล้วที่ผมได้มาจับด้านเว็บเป็นอาชีพจริงๆนับย้อนไปตั้งแต่ปี 2 จนมาถึงตอนนี้ปี 2011 ก็เป็นเวลา 5 ปีแล้วที่ได้ทำอาชีพนี้ โดยต้องบอกก่อน ว่าผมไม่เคยได้จับระบบใหญ่ ไม่เคยเจองานที่ Hit Limit ของสถาปัตยกรรม จนกระทั่งมาทำงานๆหนึ่งที่เรียกว่า &#8220;บอทเว็บ&#8221; แน่นอน OBVOC ไม่ใช่งานบอทเว็บ ตัวแรกของผม แล้วแต่ละตัวก็ไม่เคยเจอ Limit จนกระทั่งเอามาใช้งานจริง ทำแบบ Commercial จริงๆ แล้วทำให้รู้ว่าจริงๆ สิ่งที่เราคิดว่าดีตอนแรกมันอาจไม่ดีถึงตอนหลังก็ได้ เลยอยากจะมาถ่ายทอดความรู้กับนักพัฒนาหรือใครก็ตามที่ กำลังจะทำเว็บขนาดใหญ่หรือมี Transaction สูงๆแล้วก็เป็นสาเหตุว่าทำไมผมถึงต้องพัฒนาก้าวไปอีกขั้นด้วยเทคโนโลยีที่พึงมาในปัจจุบัน โดยสาเหตุที่เจอมากับตัวก็คือ</p><ol><li>เงินทุนที่่มีอย่างจำกัดทำให้เรามี Server ขนาดเล็กกว่าที่ Application เราต้องการสมมุติว่าคุณมี RAM อยู่ 1GB แล้วเป็น Shared CPU แต่คุณต้องการทำ Fulltext , การวิเคราะห์และคำนวณเพื่อนำมาทำสถิติ ซึ่งใช้ CPU 100% เกือบตลอดเวลา ดังนั้นปัญหาแรกคือ <strong>&#8220;ทรัพยากร&#8221;</strong> อย่ามีน้อยเกินไปกับขนาดตัว App แต่อย่่างว่าใครจะไปรู้ต้องลองทำๆไปแล้วเดียวถึงจะรู้เอง</li><li>ทดลองกับข้อมูลจำนวนมากๆ ปกติแล้วเราทำเว็บไซต์จะทำกับข้อมูลจำนวนน้อยๆก่อน แล้วสิ่งที่คุณจะเจอปัญหาก็คือ เมื่อมันถึงจุดๆหนึ่งที่ RAM ไม่พอพักข้อมูลของคุณใน MySQL (Database) อื่นๆระบบคุณจะช้าขึ้นไม่ต่ำกว่า 5x-20x ทำให้จากเว็บดีๆของคุณช้าในทันที โดยผมบอกได้เลยว่าปัญหานี้ไม่จำเป็นต้องทำตั้งแต่เริ่ม แต่สิ่งที่ควรทำคือหาเลขนี้ให้ได้ <strong>&#8220;อัตราการโตของข้้อมูลจริงต่อวัน&#8221;</strong> ให้เก็บข้อมูลสัก 30 วันคุณจะรู้อยู่่สองเลขก็็คือ Database โตขึ้นต่อวันเท่าไร และค่าเฉลี่ยต่อ 30 วันเท่าไร แล้วให้คุณไปหาอีกเลขหนึ่งที่สำคัญก็คือ <strong>&#8220;ฐานข้อมูลโตจากวันแรกจนถึงวันที่  30 คิดเป็นกี่ %&#8221; </strong>แล้วลองทำนายดูว่าอีก 90 วันข้างหน้ามันจะมีข้อมูลเท่าไร ซึ่งแบบนี้คือวิธีคิดง่ายๆ เรื่องจริงมันไม่ง่ายที่จะเดาแบบนี้เพราะมีเรื่อง Marketing มาเกี่ยวข้องด้วย</li><li>พอเราหาอัตราการโตข้อมูลเจอแล้ว สิ่งที่คุณควรจะทำต่อไปก็คือ &#8220;ทดลองด้วยจำนวนข้อมูลที่ทำนายไว้อีก 90 วันหรือมากกว่านั้น&#8221; โดยถ้ามั่นใจแล้วว่า Feature ไม่เปลี่ยนแปลง ผมขอแนะนำว่าให้ทดสอบแบบ Stress Test หรือทำให้สุดไปเลยคือ Insert ข้อมูลเข้าไปเรื่อยๆแล้วลอง Test ระบบว่าระบบเราเริ่มช้า ให้จดเลขนั้นไว้ไม่ว่าจะเป็นจำนวน Record หรือ Database Size แล้วลองนำกลับมาคำนวณดูโดยใช้เลขเดิมที่เรามีโดยคราวนี้เราจะหาว่า <strong>&#8220;จะใช้ระยะเวลาเท่าไรถึงจะถึงข้อมูลจำนวนที่ทำให้ช้า&#8221; </strong>โดยวิธีก็คือ ให้เอา      จำนวนข้อมูลที่ทำให้ช้า / อัตราการโตข้อมูลจริงเฉลี่ยต่อวัน  โดยถ้าอยากให้แม่นกว่าเดิมให้เอาอัตราการเติบโต (%) ไปหารอีกทีก็จะได้ข้อมูลแบบหยาบๆมาพอดูได้ว่า <strong>อีกกี่วันถึงเวลาที่เราต้องเปลี่ยนแปลงวิธีคิดกับการเข้าถึงฐานข้อมูล</strong> ถ้ามันเป็นเวลานานเป็นปีแล้วละก็ชั่งมันไปก่อนไม่ต้องทำอะไร แต่ให้รับรู้ไว้้แล้วจดว่ามันจะช้าเมื่อไร</li><li>เว็บไซต์มีหลายด้านแต่ด้านไหนจะสำคัญกว่าใครขึ้นอยู่กับแต่ละ Application โดยตัวแปรสำคัญที่ผมคิดว่าสำคัญจริงๆ ก็คือ CPU , RAM , อัตราความเร็วนในการเขียนข้อมูล , อัตราความเร็วในการอ่านข้อมูล , Bandwidth ขาเข้า-ขาออก , Webserver request per sec , Network Latency (ผมใช้ Firebug ดู)</li><li>เรื่องการทำ Fulltext Search กับ Reverse Index เนื่องจากผมต้องมีการทำการค้นหาข้อมูล เหล่านี้จากบอทที่เก็บมาได้ก็ผมข้อเท็จจริงหลายอย่างว่า การทำ Reverse Index นั้น sure กว่าเยอะว่าจะค้้นหาเจอ แต่มีข้อเสียคือเราไม่รู้ว่าเขาจะหาด้วยคำอะไร จนกว่าจะมีการใส่ข้อมูลเข้ามา ซึ่งถ้าให้ระบบไปทำ Reverse Index ทันที ณ ตอนนั้นก็คงช้า ดังนั้นคุณต้อง Weight เอาดังนี้<ul><li>Like นั้นช้า แต่ข้อมูลที่อยากจะหานั้นตรงกับความต้องการมากกว่า เมื่อข้อมูลมีมากๆนั้นวิธีนี้จะช้าขั้นเทพก็ว่าได้</li><li>Fulltext Search โดยเท่าที่ผมใช้มา มันค่อนข้างได้ผลประมาณ 70-80% เลยทีเดียวสำหรับภาษาไทย (ผมใช้ MySQL MyISAM fulltext) แต่อย่างว่า ถ้าอีก 20% นั้นเป็นสิ่งที่ลูกค้าผมต้องการหา แต่ดันหาไม่เจอเขาจะพอใจรึเปล่า ? ดังนั้นวิธีนี้คือ Speed มาก่อน , Coverage 70-80% แล้วจะช้าเมื่อเริ่มมี Complex Search เช่น ค้นหาข้อมูลที่มีคำว่า &#8220;โดม&#8221; หรือ &#8220;วโรดม&#8221; หรือ &#8220;ทศนิยม&#8221; หรือ &#8220;อื่นๆ&#8221; และไม่มีคำว่า &#8220;ทดสอบ&#8221; แบบนี้เป็นต้น</li><li>Reverse Index ข้อเสียคือไม่สามารถทำให้ค้นหาทันทีได้หรือจะต้องทำ Index ด้วยตัวเองก่อนนั้นเอง วิธีนี้ก็ใช้ Server Side Script ช่วยอย่่าง PHP เอาข้อมูลที่มีมาวิเคราะห์ว่ามี &#8220;คำนี้&#8221; ไหมเสร็จแล้ว Save ความสัมพันธ์ระหว่างข้อความกับ Keyword ถ้ามีคนค้นหาด้วย Keyword นั้นพอดีคราวหลังก็จะดึงข้อมูลขึ้นมาได้แล้ว แต่ข้อเสียมีเยอะมากคือถ้าจะทำ Complex Search นั้นเราจะต้องทำตัว Translate จาก Search Query มาเป็น SQL Query ซึ่่งเสียเวลา</li><li>Fulltext ผสม Reverse Index วิธีนี้ได้ผลดีที่สุด โดยใช้วิธีการ Union Query กันผลที่ได้คือมีความถูกต้องสูง สามารถค้นหาได้ทันที แต่ก็ไปตายที่ Complex Search อยู่ดี</li></ul></li><li>ควรจะรู้จัก <a
href="http://en.wikipedia.org/wiki/CAP_theorem">CAP Theorem</a> ซึ่งเป็นหัวใจที่ต้องเลือกว่าจริงๆ แล้วระบบเราต้องการแบบไหน ซึ่งตรงส่วนนี้ถ้ามีประสบการณ์จะเข้าใจความสำคัญในการเลือก CAP โดยทำให้เราก้าวไปเป็น Web Developer อีกขั้นหนึ่งโดยจะเข้าใจคำว่า &#8220;one size doesn&#8217;t fit all&#8221;</li><li>อย่ามองข้าม Script Automation และ Alert สองเรื่องนี้ถือว่าเป็นสิ่งที่ทำให้ชีวิตของคนเขียน Program สบายและมีความสุขได้ ถ้าขาดส่วนนี้ไปงานจะเยอะขึ้นเรื่อยๆ จนเราปวดหัวเลยทีเดียว โดย Automation ให้ได้มากที่สุดเท่าที่เราทำได้ ทั้ง Log ข้อมูล , Backup ข้อมูล , Process ข้อมูล ฯลฯ เท่าที่คอมพิวเตอร์จะทำได้ ผมมั่นใจว่าถ้าการเขียนครั้งหนึ่งสามารถแก้ปัญหาหนึ่ง ที่คุณต้องใช้เวลา 10 นาที &#8211; 30 นาทีทำต่อครั้งนั้นถือว่าคุ้มค่ามากเพราะ มันคงไม่เกิดเพียงแค่ครั้งเดียวเป็นแน่แท้ ! แล้วคุณก็เอาไปใช้กับระบบอื่นได้อีกด้วย อีกอันที่สำคัญคือระบบ Alert คุณเบื่อไหมที่ต้องค่อย Monitor อะไรบ้างอย่างบ่อยๆทั้งๆที่เรื่องมันไม่ได้เกิดตลอดเวลา เช่น ระบบกำลังจะ Memory หมด , CPU หมด , มี Process บางตัวใช้ CPU เกิน 80% แล้ว Log ฯลฯ ซึ่งเรื่องราวนี้ขึ้นอยู่กับว่าคุณต้องการให้มันเป็น Automation หรือ Alert</li><li>Backup Backup Backup โดย Backup ที่ว่านี้คืออย่า Backup เฉพาะในเครื่องเดียวกัน ให้มีการกระจายข้อมูลไปที่อื่นด้วย หรือนำมาเก็บไว้ในเครื่องตัวเอง เพราะข้อมูลเป็นสิ่งสำคัญที่สุดของเว็บถ้ามันหายไป เว็บเราก็คงเหมือนเริ่มใหม่กันเลย ดังนั้นอย่าลืม Backup ไม่ว่าจะด้วยวิธีการไหน แต่ผมแนะนำ <a
href="http://en.wikipedia.org/wiki/Incremental_backup">Incremental Backup</a> แต่ถ้ามันทำได้ยาก ก็แนะนำว่า Backup ทั้งหมดไปเถอะดีกว่าหายครับ</li></ol><p>จบแล้ว 8 ข้อโดยจริงๆยังมีอีกมาก แต่เรื่องเหล่านี้เป็นเรื่องที่ผมเจอตอนทำ OBVOC เลยอยากจะนำมา Share ให้ฟังกันครับ <img
src='http://www.dominixz.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /></p> Similar Posts:<ul><li><a
href="http://www.dominixz.com/blog/programming-solution/tuning-mysql-trace-yourself-and-understand-variable/" rel="bookmark" title="September 11, 2011">Tuning MySQL : สำรวจตัวเองและเข้าใจตัวแปร</a></li><li><a
href="http://www.dominixz.com/blog/programming-solution/tuning-mysql-case-study-obvoc-obhunter/" rel="bookmark" title="September 13, 2011">Tuning MySQL : Case Study OBVOC/OBHUNTER</a></li><li><a
href="http://www.dominixz.com/blog/review/oracle-xe-10g-vs-mysql-v516/" rel="bookmark" title="February 11, 2008">Oracle XE 10g [vs] MySQL v5.1.6 สงครามของฟรี !</a></li></ul>]]></content:encoded> <wfw:commentRss>http://www.dominixz.com/blog/programming-solution/8-things-for-young-web-development/feed/</wfw:commentRss> <slash:comments>3</slash:comments> </item> <item><title>Facebook API สำหรับดู Share Count ของ Link</title><link>http://www.dominixz.com/blog/programming-solution/how-to-get-share-count-link-on-facebook/</link> <comments>http://www.dominixz.com/blog/programming-solution/how-to-get-share-count-link-on-facebook/#comments</comments> <pubDate>Fri, 24 Jun 2011 18:45:17 +0000</pubDate> <dc:creator>DominixZ</dc:creator> <category><![CDATA[วิธีแก้ปัญหาเขียนโปรแกรม]]></category> <category><![CDATA[เคล็คลับซอฟต์แวร์]]></category><guid
isPermaLink="false">http://www.dominixz.com/blog/?p=1326</guid> <description><![CDATA[เนื่องจากบางท่านอาจจะได้นำไปใช้ประโยชน์ เช่น นำ cron ไปเก็บแล้วก็ เอามาจัดอันดับภายใน blog ของตัวเองอะไรก็ว่าไปโดยใช้แบบนี้ได้เลยครับ https://graph.facebook.com/?ids=http://www.dominixz.com/blog/review/software/10-iphone-4-apps-that-i-use-episode-1 ลองเอาไปแปะบน Browser ดูครับมันจะ Return มาเป็น Json หน้าที่ของเราคือ ถ้าใน PHP ก็คือ $var = json_decode(file_get_contents(url)); เพียงเท่านี้จะได้ตัวแปรที่มี object share count มาใช้งานแล้วครับผม Similar Posts:มารู้จัก Facebook Graph API กัน PHP เรียกใช้ Web Service ของ .NET ด้วยการส่งและรับ Object Blog ชิลๆ Style วันเสาร์อาทิตย์ : Make it for me]]></description> <content:encoded><![CDATA[<p>เนื่องจากบางท่านอาจจะได้นำไปใช้ประโยชน์ เช่น นำ cron ไปเก็บแล้วก็ เอามาจัดอันดับภายใน blog ของตัวเองอะไรก็ว่าไปโดยใช้แบบนี้ได้เลยครับ</p><p><a
href="https://graph.facebook.com/?ids=http://www.dominixz.com/blog/review/software/10-iphone-4-apps-that-i-use-episode-1">https://graph.facebook.com/?ids=http://www.dominixz.com/blog/review/software/10-iphone-4-apps-that-i-use-episode-1</a></p><p>ลองเอาไปแปะบน Browser ดูครับมันจะ Return มาเป็น Json หน้าที่ของเราคือ ถ้าใน PHP ก็คือ $var = json_decode(file_get_contents(url)); เพียงเท่านี้จะได้ตัวแปรที่มี object share count มาใช้งานแล้วครับผม</p> Similar Posts:<ul><li><a
href="http://www.dominixz.com/blog/tech-news/nice-to-know-facebook-graph-api/" rel="bookmark" title="May 8, 2010">มารู้จัก Facebook Graph API กัน</a></li><li><a
href="http://www.dominixz.com/blog/programming-solution/php-call-dot-net-webservice-that-require-object-param/" rel="bookmark" title="September 12, 2008">PHP เรียกใช้ Web Service ของ .NET ด้วยการส่งและรับ Object</a></li><li><a
href="http://www.dominixz.com/blog/productivity/blog-chill-style-only-for-me/" rel="bookmark" title="July 7, 2007">Blog ชิลๆ Style วันเสาร์อาทิตย์ : Make it for me</a></li></ul>]]></content:encoded> <wfw:commentRss>http://www.dominixz.com/blog/programming-solution/how-to-get-share-count-link-on-facebook/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>วิธี Search MySQL ด้วย Fulltext Order By Query เร็วและแรง</title><link>http://www.dominixz.com/blog/geek-tips/increase-speed-mysql-fulltext-order-by-with-this-mindset/</link> <comments>http://www.dominixz.com/blog/geek-tips/increase-speed-mysql-fulltext-order-by-with-this-mindset/#comments</comments> <pubDate>Thu, 05 May 2011 09:50:43 +0000</pubDate> <dc:creator>DominixZ</dc:creator> <category><![CDATA[วิธีแก้ปัญหาเขียนโปรแกรม]]></category> <category><![CDATA[เคล็คลับซอฟต์แวร์]]></category> <category><![CDATA[เคล็ดลับ]]></category><guid
isPermaLink="false">http://www.dominixz.com/blog/?p=1250</guid> <description><![CDATA[ถ้าใครเคยใช้ Fulltext จะรู้ว่า Fulltext นั้นค้นหาข้อมูลเร็วมาก แต่ก็ต้องมาเจ็บปวดเมื่อต้องใช้ &#8220;ORDER BY&#8221; เมื่อ Record ยิ่งเยอะยิ่งช้ามากๆ เมื่อคืนผมเจอปัญหาก็คิดไม่ตก คิดไปคิดมาไปอ่านการทำงานของ Order By Optimization ซึ่งอ่านไปแล้วก็ลองทำตามก็ไม่ได้ผล แม้จะอัพเรื่องจำนวน Memory ของ sort_buffer_size , read_rnd_buffer_size ก็ไม่หายตอนนั้นก็เกือบตี 4 แล้วถอดใจ กะว่าได้ใช้ Inverse Index แน่ๆแต่พอนอนลงแล้วนึกทบทวนเกี่ยวกับที่ได้อ่าน Order By Optimization จำประโยคได้ว่า &#8220;Read all rows according to key or by table scanning. Rows that do not match the WHERE clause are skipped.&#8221; คือถ้ามีการใช้ [...]]]></description> <content:encoded><![CDATA[<p>ถ้าใครเคยใช้ Fulltext จะรู้ว่า Fulltext นั้นค้นหาข้อมูลเร็วมาก แต่ก็ต้องมาเจ็บปวดเมื่อต้องใช้ &#8220;ORDER BY&#8221; เมื่อ Record ยิ่งเยอะยิ่งช้ามากๆ เมื่อคืนผมเจอปัญหาก็คิดไม่ตก คิดไปคิดมาไปอ่านการทำงานของ <a
href="http://dev.mysql.com/doc/refman/5.0/en/order-by-optimization.html">Order By Optimization</a> ซึ่งอ่านไปแล้วก็ลองทำตามก็ไม่ได้ผล แม้จะอัพเรื่องจำนวน Memory ของ sort_buffer_size , read_rnd_buffer_size ก็ไม่หายตอนนั้นก็เกือบตี 4 แล้วถอดใจ กะว่าได้ใช้ Inverse Index แน่ๆแต่พอนอนลงแล้วนึกทบทวนเกี่ยวกับที่ได้อ่าน Order By Optimization จำประโยคได้ว่า</p><p>&#8220;Read all rows according to key or by table scanning. Rows               that do not match the <code>WHERE</code> clause are               skipped.&#8221;</p><p>คือถ้ามีการใช้ Where มันจะ Skip ข้อมูลตรงส่วนที่เหลือทิ้งไป งั้นเราก็มาดูตัวอย่างกันครับว่า Query ของผมเป็นยังไง</p><blockquote><p>SELECT id,title,created_at,updated_at FROM pages WHERE root_page_id IN (1,2,3,4,5,6,7) AND MATCH (title,content) AGAINST (&#8216;&#8221;ais&#8221; &#8220;dtac&#8221; &#8220;true&#8221;&#8216; IN BOOLEAN MODE) AND id NOT IN (1000,1001,1002,1003) ORDER BY created_at DESC LIMIT 0,20</p></blockquote><p>โดยทั้งหมดนี้ผมทำ index แบบธรรมดาคือไม่ได้ composition ทั้งหมดแต่ก็มี index ทุก field ใน query นี้แต่ผลที่ได้ของเดิมก็คือ 20 sec ต่อมาก็เลยทดสอบว่าถ้า scope created_at ไว้น่าจะเร็วขึ้น ตามที่เขาเขียนข้างบนเลยกลายเป็น</p><blockquote><p>SELECT id,title,created_at,updated_at FROM pages WHERE created_at &gt;= &#8217;2011-04-05 23:59:59&#8242; AND created_at &lt;= &#8217;2011-05-05 23:59:59&#8242; root_page_id IN  (1,2,3,4,5,6,7) AND MATCH (title,content) AGAINST (&#8216;&#8221;ais&#8221; &#8220;dtac&#8221; &#8220;true&#8221;&#8216;  IN BOOLEAN MODE) AND id NOT IN (1000,1001,1002,1003) ORDER BY  created_at DESC LIMIT 0,20</p></blockquote><p>แล้วก็ลองทดสอบดูสรุปก็ยังเป็น 20 วินาทีอยู่ดีช้าอยู่ดี ก็ส่งสัยว่าทำไมๆๆ ก็เลยนึกถึงความเป็นจริงลองคิดว่า MySQL เป็นคน &#8220;created_at&#8221; ต่อให้มี index เราก็ต้องไปดู index ทั้งหมดอยู่ดีว่า id ไหนบ้างนะที่อยู่ใน range นี้โดยลองคิดดูว่ามีสัก &gt; 500K เสร็จแล้วยังไม่วายโดน order_by อีกก็เลยยังช้าเหมือนเดิม แล้ววิธีคิดแบบไหนละที่จะทำให้เร็วขึ้น</p><p>ลองคิดดูว่าถ้าคุณมีตระกร้าของแต่ละคำที่ต้องการค้นหา (ในที่นี้ก็คือ fulltext และ index) เสร็จแล้วเอาตระกร้าเหล่านั้นออกมาก่อน แล้วค่อยมาเรียงมันจะเร็วกว่าไหม ? (เพราะแบบอันแรกเรายังไม่เทตระกร้าแล้วค่อยออกมาเรียง scope แต่เป็นการหา &#8220;ตะกร้าที่เกี่ยวข้อง&#8221; แล้ว &#8220;เรียงทั้งหมดใน table&#8221; เพราะยังไม่เท่ตะกร้าเนี้ยและ) คงส่งสัยใช่ไหมว่า MySQL มันจะโง่ยังงั้นเลยหรอ อันนี้ผมก็ไม่แน่ใจ แต่ผมใช้แบบ Query นี้</p><blockquote><p>SELECT id,title,created_at,updated_at FROM pages WHERE id IN (SELECT id FROM pages WHERE root_page_id IN (1,2,3,4,5,6,7) AND MATCH (title,content) AGAINST (&#8216;&#8221;ais&#8221; &#8220;dtac&#8221; &#8220;true&#8221;&#8216; IN BOOLEAN MODE) AND id NOT IN (1000,1001,1002,1003) ) ORDER BY created_at DESC LIMIT 0,20</p></blockquote><p>เชื่อไหมว่า Query ผมจาก 20 วินาทีเหลือเพียง 0.3-1 วินาทีเท่านั้น !! นั้นหมายความว่าเร็วขึ้น 20x &#8211; 70x เท่าเลยทีเดียวนะครับ โดยไม่ต้องไปใช้ Inverse Index แต่ใช้วิธีนี้ แค่นี้ผมก็ยังไม่ต้องรีบเปลี่ยน Software Architecture และไม่ต้องไปเปลื้อง RAM จำนวนมากเพื่อให้ตอบโจทย์นี้เพราะมันจะต้องกิน RAM ประมาณ 6GB ในข้อมูลขนาด 650,000 rows ของผมซึ่งผมไม่มี ฝากบทความนี้กับคนที่กำลังจะหาวิธีใช้ Fulltext กับ Order By นะครับ</p><p>โดย Query เนี้ยผมทำกับระบบชื่อ <a
href="http://thumbsup.in.th/2011/05/onebitmatter/">OB-VOC ครับลองอ่านดูที่ Thumbsup ครับ</a></p> Similar Posts:<ul><li><a
href="http://www.dominixz.com/blog/tech-news/increase-speed-mysql-fulltext-order-by-with-this-mindset-ep-2/" rel="bookmark" title="May 13, 2011">วิธี Search MySQL ด้วย Fulltext Order By Query เร็วและแรง 2</a></li><li><a
href="http://www.dominixz.com/blog/geek-tips/condition-if-subuqery-mysql-for-your-result/" rel="bookmark" title="April 24, 2011">วิธีใช้เงื่อนไข IF , Sub-Query ฯลฯใน MySQL เพื่อให้ได้ผลลัพธ์ที่ต้องการ</a></li><li><a
href="http://www.dominixz.com/blog/programming-solution/8-things-for-young-web-development/" rel="bookmark" title="August 15, 2011">ประสบการณ์ 8 ข้อที่อยากให้เด็กรุ่นใหม่รู้กับการทำ Web Development</a></li></ul>]]></content:encoded> <wfw:commentRss>http://www.dominixz.com/blog/geek-tips/increase-speed-mysql-fulltext-order-by-with-this-mindset/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>วิธีใช้เงื่อนไข IF , Sub-Query ฯลฯใน MySQL เพื่อให้ได้ผลลัพธ์ที่ต้องการ</title><link>http://www.dominixz.com/blog/geek-tips/condition-if-subuqery-mysql-for-your-result/</link> <comments>http://www.dominixz.com/blog/geek-tips/condition-if-subuqery-mysql-for-your-result/#comments</comments> <pubDate>Sat, 23 Apr 2011 18:58:28 +0000</pubDate> <dc:creator>DominixZ</dc:creator> <category><![CDATA[วิธีแก้ปัญหาเขียนโปรแกรม]]></category> <category><![CDATA[เคล็ดลับ]]></category><guid
isPermaLink="false">http://www.dominixz.com/blog/?p=1240</guid> <description><![CDATA[เนื่องจากผมจะต้องทำ Report พร้อมมีสมการบางอย่าง เพื่อเป็นการคำนวณ ซึ่งผมใช้ PHP กับ MySQL เป็นหลัก โดยปัญหาที่มักจะเกิดบ่อยๆก็คือ &#8220;ดึงข้อมูลจาก Database มาคำนวณที่ PHP แล้วก็เอามาเรียงใส่ Array ใหม่เป็นข้อมูลชุดใหม่&#8221; และยังมีเหตุการอื่นๆอีกเช่น ไม่ยอม Join Table แล้ว GET ข้อมูลจาก Table หนึ่งไปใส่อีก Table หนึ่งทำให้ Performance ช้าอีก วันนี้ผมเลยขอแนะนำตัวที่เราได้ใช้บ่อยๆกันใน MySQL กันนะครับผมก็พึงลองสดๆร้อนๆเลย CASE CASE value WHEN [compare_value] THEN result [WHEN [compare_value] THEN result ...] [ELSE result] END จริงๆผมสับสนระหว่าง CASE กับ IF แต่พอใช้แล้วก็เข้าใจขึ้น โดยผมมองว่า CASE [...]]]></description> <content:encoded><![CDATA[<p>เนื่องจากผมจะต้องทำ Report พร้อมมีสมการบางอย่าง เพื่อเป็นการคำนวณ ซึ่งผมใช้ PHP กับ MySQL เป็นหลัก โดยปัญหาที่มักจะเกิดบ่อยๆก็คือ <strong>&#8220;ดึงข้อมูลจาก Database มาคำนวณที่ PHP แล้วก็เอามาเรียงใส่ Array ใหม่เป็นข้อมูลชุดใหม่&#8221; </strong>และยังมีเหตุการอื่นๆอีกเช่น ไม่ยอม Join Table แล้ว GET ข้อมูลจาก Table หนึ่งไปใส่อีก Table หนึ่งทำให้ Performance ช้าอีก</p><p>วันนี้ผมเลยขอแนะนำตัวที่เราได้ใช้บ่อยๆกันใน MySQL กันนะครับผมก็พึงลองสดๆร้อนๆเลย</p><h3><strong>CASE</strong></h3><p><a
href="http://dev.mysql.com/doc/refman/5.0/en/control-flow-functions.html#operator_case"><code>CASE <em><code>value</code></em> WHEN           [<em><code>compare_value</code></em>] THEN <em><code>result</code></em> [WHEN           [<em><code>compare_value</code></em>] THEN <em><code>result</code></em> ...] [ELSE <em><code>result</code></em>] END</code></a></p><p>จริงๆผมสับสนระหว่าง CASE กับ IF แต่พอใช้แล้วก็เข้าใจขึ้น โดยผมมองว่า CASE คือการ FILTER ข้อมูล แต่ IF เป็นเงื่อนไข แต่ปกติเราเขียนโปรแกรมมักใช้ IF เป็นการ FILTER ข้อมูล แต่ใน Database มักแยกกันชัดเจน ยกตัวอย่าง เช่น if(number == 1) ใน php ที่จริงคือ CASE WHEN number = 1 ทำนองนั้นครับ ตัวอย่างที่ชัดเจนคือ</p><blockquote><p>SELECT page_id , SUM(CASE WHEN score = 1 THEN 1 ELSE 0 END) AS good , SUM(CASE WHEN score = 0 THEN 1 ELSE 0 END) AS neutral , SUM(CASE WHEN score = -1 THEN 1 ELSE 0 END) AS bad<br
/> FROM sentiments</p></blockquote><p>โดยใน Table มี Field หนึ่งที่เก็บ score ซึ่งส่วนใหญ่แบ่งเป็น 1 , 0 , -1 ซึ่งผมต้องการ 3 เลขนี้ขึ้นมาใน Row เดียวผมเลยต้องใช้วิธีนี้ เพราะมันจะเกี่ยวโยงกับ Subquery เพื่อนำไปใช้ต่อในการคำนวณ ดังนั้นมันเลยเป็นสิ่งจำเป็นที่ต้องได้ค่าเหล่านี้มาอยู่ใน Row เดียว</p><h3><strong>IF</strong></h3><p><a
href="http://dev.mysql.com/doc/refman/5.0/en/control-flow-functions.html#function_if"><code>IF(<em><code>expr1</code></em>,<em><code>expr2</code></em>,<em><code>expr3</code></em>)</code></a><br
/> เป็นการใส่เงื่อนไขอย่างที่อธิบายก่อนหน้านี้ โดยวิธีใช้คือ  IF(SUM(score) &lt;  80,IF(SUM(score) &lt; 50,&#8217;F',&#8217;C'),&#8217;A') มันก็คือ IF ELSE ใน PHP นั้นเอง แต่สิ่งเดียวที่มันทำไม่ได้คือ IF(score == 1,&#8217;YES&#8217;,'NO&#8217;) ทำนองนี้ เน้นอีกครั้งนะครับ <span
style="color: #ff0000;">ทำไม่ได้</span> ดังนั้นเราเลยต้องใช้ CASE มาผสมกัน</p><h3>อื่นๆ</h3><p>อาจจะมีบางคนไม่รู้ว่า จริงๆแล้ว SQL สามารถ + &#8211; * / ( ) ได้ยกตัวอย่าง เช่น SELECT page_id , score/100 FROM sentiments เป็นต้น</p><h2>รู้พื้นฐานแล้วแต่ก็คงยังไม่พอต้องผสมให้เป็น</h2><p>โดยผมจะลองยกตัวอย่าง Query ซ้อน Query มาให้ดูสักอันจากของจริงนะครับ</p><blockquote><p>SELECT page_id,create_date, IF(ABS((((good/devideval) + (neutral/devideval)) &#8211; ((bad/devideval) + (neutral/devideval)))) &gt; 7,IF((((good/devideval) + (neutral/devideval)) &#8211; ((bad/devideval) + (neutral/devideval))) &gt;0,1,-1),0) AS score<br
/> FROM<br
/> (<br
/> SELECT page_id , SUM(CASE WHEN score = 1 THEN 1 ELSE 0 END) AS good ,SUM(CASE WHEN score = 0 THEN 1 ELSE 0 END) AS neutral , SUM(CASE WHEN score = -1 THEN 1 ELSE 0 END) AS bad , COUNT(score) as total , (COUNT(score) / 100) as devideval , DATE(created_at) AS create_date<br
/> FROM `sentiments`<br
/> WHERE user_id = 1 GROUP BY page_id,DATE(created_at)<br
/> ) AS sentiment_result</p></blockquote><p>โดยแม้จะเป็น Query ที่ดูยากสักหน่อย แต่ผมจะอธิบาย SELECT ล่างก่อนนะครับโดยจะอ่านเป็นประมาณนี้ครับ</p><p>&#8220;ให้ทำการเลือก page_id , ผลรวมของ score โดย score มีค่าเป็น 1 ให้มีค่าเป็น 1 อย่างอื่นเป็น 0 , ผลรวมของ score โดย score มีค่าเป็น 0 ให้มีค่าเป็น 1 อย่างอื่นเป็น 0 เป็น good , ผลรวมของ score โดย score มีค่าเป็น 0 ให้มีค่าเป็น 1 อย่างอื่นเป็น 0 เป็น neutral , ผลรวมของ score โดย score มีค่าเป็น -1 ให้มีค่าเป็น 1 อย่างอื่นเป็น 0&#8243;</p><p>อธิบายเพิ่มเติมตรงส่วนนี้คือ การที่ต้องทำให้ต้องมีค่าเป็น 1 เป็น 0 นั้นเพราะความต้องการของผมคือ <strong>&#8220;จำนวนนับของ score 1 , 0 และ -1&#8243;</strong> เลยต้องทำแบบนั้น จะ COUNT ก็ได้เช่นกัน แต่ผมขี้เกียจแก้ของผมที่ทำได้แล้วเท่านั้นเอง</p><p>ส่วนที่เหลือก็ Where ตามปกติ แต่ที่นี้ผมต้องอธิบายเพิ่มเพราะผมนำ SELECT อันล่างไปเป็นข้อมูลของ SELECT ข้างบนดังนั้นตอนนี้ผมเลยมี page_id , good , neutral , bas , total , devideval , create_date ที่สามารถเรียกใช้งานได้ ใน SELECt ด้านบนผมเลยมาทำสมการเลข สังเกตุว่าผมใส่ ( ) ค่อนข้างมาก เพื่อความมั่นใจว่า มันจะหารก่อนแล้วค่อยนำมา + &#8211; กันเสร็จแล้วผมก็ยังใช้ IF ELSE ฉบับ MySQL อีกด้วยคือ IF(express,IF(express,result1,result2),result3) ทำนองนั้นครับ</p><h2>ประโยชน์ที่ได้รับสำหรับการใช้การคำนวณอยู่ใน Database</h2><ul><li>เร็วไม่เปลื้อง  CPU , Memory ในการทำ Array ชุดใหญ่ใน PHP</li><li>สำหรับผม Maintenance ทำได้สะดวกกว่าใช้ PHP SQL สลับไปสลับมา</li></ul><p>โดยหลักๆคือ 2 ข้อแต่ประโยชน์จะทวีคูณ หากนำไปใช้กับ PHP อย่างเหมาะสม โดยคำเตือนขอเดียวก็คือ &#8220;ให้รู้ Limit ของ SQL และไม่จำเป็นต้องตั้งเงื่อนไขว่า จะได้ข้อมูลเหล่านี้ด้วย SQL ล้วนๆ มีบางกรณีของผมซึ่งใช้ Query เดิมได้แต่ต้องนำ good*1 , neutral*0 , bad*-1 แล้วนำมา + กันทั้งหมด ซึ่งตามจริงแล้วการจะได้เช่นนั้นผมจะต้อง SELECT อีกครั้งหนึ่งซึ่งมันสุดโต่งเกินไป ผมเลยหยุดที่ก่อน Step นั้นแล้วเวลานำไปใส่ใน Report ผมก็ใช้ PHP + &#8211; เอาแต่ทีนี้มันง่ายแล้วไงครับ เพราะใน Row ก็มี good , neutral , bad มาให้พร้อมแล้วแค่ใส่สมการ เอาไปแสดงผลเป็นอันเสร็จ วันนี้ผมลาไปก่อนหวังว่ามีประโยชน์ไม่น้อยสวัสดีครับ <img
src='http://www.dominixz.com/blog/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /></p> Similar Posts:<ul><li><a
href="http://www.dominixz.com/blog/tech-news/increase-speed-mysql-fulltext-order-by-with-this-mindset-ep-2/" rel="bookmark" title="May 13, 2011">วิธี Search MySQL ด้วย Fulltext Order By Query เร็วและแรง 2</a></li><li><a
href="http://www.dominixz.com/blog/geek-tips/increase-speed-mysql-fulltext-order-by-with-this-mindset/" rel="bookmark" title="May 5, 2011">วิธี Search MySQL ด้วย Fulltext Order By Query เร็วและแรง</a></li><li><a
href="http://www.dominixz.com/blog/programming-solution/how-to-call-stored-procedure-php-5-2-6/" rel="bookmark" title="August 8, 2009">วิธีเรียกใช้ Call Stored Procedure ของ PHP 5.2.6</a></li></ul>]]></content:encoded> <wfw:commentRss>http://www.dominixz.com/blog/geek-tips/condition-if-subuqery-mysql-for-your-result/feed/</wfw:commentRss> <slash:comments>2</slash:comments> </item> <item><title>วิธีเรียกใช้ Call Stored Procedure ของ PHP 5.2.6</title><link>http://www.dominixz.com/blog/programming-solution/how-to-call-stored-procedure-php-5-2-6/</link> <comments>http://www.dominixz.com/blog/programming-solution/how-to-call-stored-procedure-php-5-2-6/#comments</comments> <pubDate>Sat, 08 Aug 2009 04:30:48 +0000</pubDate> <dc:creator>DominixZ</dc:creator> <category><![CDATA[วิธีแก้ปัญหาเขียนโปรแกรม]]></category><guid
isPermaLink="false">http://www.dominixz.com/blog/?p=806</guid> <description><![CDATA[พอดีผมมีปัญหาในการเรียก Stored Procedure ด้วย mysql_query แบบธรรมดาซึ่งมันขึ้นว่า Stored Procedure Context ไม่เหมือนกัน หลังจากที่ไปลองๆอ่านจากหลายๆเว็บแล้ว ผมว่าคงเป็นปัญหาของ Version นี้ทางแก้ก็คือต้องรอ Version ต่อไป หรือไม่ก็ใช้ PDO ซะ !! PDO คือตัวติดต่อกับฐานข้อมูลซึ่งไม่ได้ติดต่อได้เฉพาะ MySQL แต่ติดต่อได้มากมายไม่ว่าจะเป็น Oracle , MS SQL , PostgreSQL ฯลฯ ส่วนวิธีเรียกใช้นั้นไม่ยากเพียงแต่ต้องไปเปิด extension ของ php นะครับซึ่งใครจะใช้สำหรับ Database ตัวไหนมันจะเป็นชื่อประมาณนี้ pdo_Database เมื่อเปิดเสร็จแล้วมาดูวิธีการใช้งานเรียก Stored Procedure กันซึ่งเหมือนกับการ Query ข้อมูลเดะๆ สังเกตุได้ว่าเหมือน Query เปะแต่จะเป็นแนวใช้ Object แทนแบบ functional เพิ่มเติดอีกนิดถ้าเรารู้อยู่แล้วว่ามันจะออกมาแถวเดียวเราสามารถทำแบบนี้ได้เลยนะครับ แต่การเขียนแบบนี้ ก็อาจมีข้อผิดพลาดเกิดขึ้นได้ในกรณีที่ไม่มีค่าส่งกลับมา ดังนั้นเราควรเขียนดักไว้สักเล็กน้อยแบบนี้ [...]]]></description> <content:encoded><![CDATA[<p>พอดีผมมีปัญหาในการเรียก Stored Procedure ด้วย mysql_query แบบธรรมดาซึ่งมันขึ้นว่า Stored Procedure Context ไม่เหมือนกัน หลังจากที่ไปลองๆอ่านจากหลายๆเว็บแล้ว ผมว่าคงเป็นปัญหาของ Version นี้ทางแก้ก็คือต้องรอ Version ต่อไป หรือไม่ก็ใช้ PDO ซะ !!</p><p>PDO คือตัวติดต่อกับฐานข้อมูลซึ่งไม่ได้ติดต่อได้เฉพาะ MySQL แต่ติดต่อได้มากมายไม่ว่าจะเป็น Oracle , MS SQL , PostgreSQL ฯลฯ ส่วนวิธีเรียกใช้นั้นไม่ยากเพียงแต่ต้องไปเปิด extension ของ php นะครับซึ่งใครจะใช้สำหรับ Database ตัวไหนมันจะเป็นชื่อประมาณนี้ pdo_<em>Database </em>เมื่อเปิดเสร็จแล้วมาดูวิธีการใช้งานเรียก Stored Procedure กันซึ่งเหมือนกับการ Query ข้อมูลเดะๆ</p><pre class="brush: php; title: ; notranslate">
$pdo = new PDO('mysql:dbname=duocorevp;host=127.0.0.1;port=8889', 'root', 'root');
print '&amp;lt;h3&amp;gt;PDO: simple select&amp;lt;/h3&amp;gt;';
foreach($pdo-&amp;gt;query('call countUsers();') as $row)
{
 print_r($row);
}
</pre><p>สังเกตุได้ว่าเหมือน Query เปะแต่จะเป็นแนวใช้ Object แทนแบบ functional เพิ่มเติดอีกนิดถ้าเรารู้อยู่แล้วว่ามันจะออกมาแถวเดียวเราสามารถทำแบบนี้ได้เลยนะครับ</p><pre class="brush: php; title: ; notranslate">
$result = $pdo-&amp;gt;query('call countUsers()')-&amp;gt;fetch();
</pre><p>แต่การเขียนแบบนี้ ก็อาจมีข้อผิดพลาดเกิดขึ้นได้ในกรณีที่ไม่มีค่าส่งกลับมา ดังนั้นเราควรเขียนดักไว้สักเล็กน้อยแบบนี้</p><pre class="brush: php; title: ; notranslate">
if($pdo-&amp;gt;query('call countUsers()'))
$result = $pdo-&amp;gt;fetch();
else
    $result = null;
</pre><p>แบบนี้เป็นต้นครับ ไม่ยากเลยใช่ไหมครับวันนี้ผมลาไปก่อนแล้วครับ <img
src='http://www.dominixz.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </pre> Similar Posts:<ul><li><a
href="http://www.dominixz.com/blog/geek-tips/condition-if-subuqery-mysql-for-your-result/" rel="bookmark" title="April 24, 2011">วิธีใช้เงื่อนไข IF , Sub-Query ฯลฯใน MySQL เพื่อให้ได้ผลลัพธ์ที่ต้องการ</a></li><li><a
href="http://www.dominixz.com/blog/review/oracle-xe-10g-vs-mysql-v516/" rel="bookmark" title="February 11, 2008">Oracle XE 10g [vs] MySQL v5.1.6 สงครามของฟรี !</a></li><li><a
href="http://www.dominixz.com/blog/tech-news/increase-speed-mysql-fulltext-order-by-with-this-mindset-ep-2/" rel="bookmark" title="May 13, 2011">วิธี Search MySQL ด้วย Fulltext Order By Query เร็วและแรง 2</a></li></ul>]]></content:encoded> <wfw:commentRss>http://www.dominixz.com/blog/programming-solution/how-to-call-stored-procedure-php-5-2-6/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>10 ข้อแนะนำเวลาใช้ PHP MVC Framework</title><link>http://www.dominixz.com/blog/programming-solution/suggest-solution-for-php-mvc-framework/</link> <comments>http://www.dominixz.com/blog/programming-solution/suggest-solution-for-php-mvc-framework/#comments</comments> <pubDate>Mon, 15 Jun 2009 18:19:12 +0000</pubDate> <dc:creator>DominixZ</dc:creator> <category><![CDATA[วิธีแก้ปัญหาเขียนโปรแกรม]]></category><guid
isPermaLink="false">http://www.dominixz.com/blog/?p=704</guid> <description><![CDATA[ห่างหายไปนานพอตัวแถมยังติดค้าง Barcamp Bangkok วันที่ 2 อีกถ้าว่างแล้วเดียวผมจะรีบเขียนเลยครับผม เอาละเข้าเรื่องกันเลยวันนี้ผมจะฝากข้อแนะนำง่ายๆไว้ละกันครับ 10 ข้อ แยก Business Logic ให้ออกจาก View อย่างชัดเจน เช่น ในโค้ดส่วนของ View ไม่ควรมีประมาณนี้ครับ if(user_login() &#38;&#38; not_admin()) ควรจะเปลี่ยนให้เป็นตัวแปรแค่นี้พอ if($logged_in_and) เพื่อความง่ายในการอ่านและแยกส่วน Business Logic พยายามอย่าเขียนโค้ดซ้ำ ถ้ารู้ตัวว่ากำลังเขียนโค้ดซ้ำ ให้พยายามหาทางแก้ เช่น เขียน function is_login() ใน user class เพื่อถามว่า login รึยัง แต่ดันใช้ function นี้ในคลาสอื่นๆ ดังนั้นเราควรจะย้าย function is_login() ไปอยู่ภายใต้คลาสแม่ที่แต่ละ class อื่นๆของเราถูก implement ขึ้นมาเช่น Controller หลายๆ Framework จะไม่มีการกำหนดว่าเราต้องกำหนดชื่อในไฟล์และโฟลเดอร์ [...]]]></description> <content:encoded><![CDATA[<p>ห่างหายไปนานพอตัวแถมยังติดค้าง Barcamp Bangkok วันที่ 2 อีกถ้าว่างแล้วเดียวผมจะรีบเขียนเลยครับผม <img
src='http://www.dominixz.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> เอาละเข้าเรื่องกันเลยวันนี้ผมจะฝากข้อแนะนำง่ายๆไว้ละกันครับ 10 ข้อ</p><ol><li>แยก Business Logic ให้ออกจาก View อย่างชัดเจน เช่น ในโค้ดส่วนของ View ไม่ควรมีประมาณนี้ครับ<br
/> if(user_login() &amp;&amp; not_admin()) ควรจะเปลี่ยนให้เป็นตัวแปรแค่นี้พอ if($logged_in_and) เพื่อความง่ายในการอ่านและแยกส่วน Business Logic</li><li>พยายามอย่าเขียนโค้ดซ้ำ ถ้ารู้ตัวว่ากำลังเขียนโค้ดซ้ำ ให้พยายามหาทางแก้ เช่น เขียน function is_login() ใน user class เพื่อถามว่า login รึยัง แต่ดันใช้ function นี้ในคลาสอื่นๆ ดังนั้นเราควรจะย้าย function is_login() ไปอยู่ภายใต้คลาสแม่ที่แต่ละ class อื่นๆของเราถูก implement ขึ้นมาเช่น Controller</li><li>หลายๆ Framework จะไม่มีการกำหนดว่าเราต้องกำหนดชื่อในไฟล์และโฟลเดอร์ view อย่างไร และเวลาเรียกก็ต้องทำเอง ผมมีสิ่งที่ผมลองมาแล้ว รู้สึกว่าไม่ได้ผลคือการที่พยายามจะเรียก view ที่ประกอบกัน เช่นมี header footer จากภายใน Controller สรุปแล้วมันยุ่งเหยิงมาก ส่วนวิธีแก้ก็คือในไฟล์ view แต่ละหน้านั้นให้ include header footer ลงไปเลย แต่พยายามใช้เป็นแบบ function ทำเองจะได้ปรับแก้ไขสะดวกเพราะมันจะมีพวก parameter บางอย่างที่ต้องเปลี่ยนไปในแต่ละหน้าแต่ใช้ header ตัวเดียวกัน เช่น title</li><li>เรื่องการ validation และเรื่องจัดการเวลาเกิด error เป็นสิ่งที่ไม่ควรละเลย เพราะเราต้องทำการ validation กันอยู่หลายๆหน้า ซึ่งมีลักษณะคล้ายกันดังนั้น ถ้าเขียนไม่ดีละก็เสียเวลาเขียนซ้ำบ่อยแน่</li><li>ค่า Default เป็นเรื่องที่ไม่ควรละเลย เช่น ถ้าตัวแปรนี้ไม่ได้ถูก set มาควรมีค่าเป็นอะไรเพราะใช้บ่อยในพวก form</li><li>ควรหา Editor ที่สามารถใช้กับ PHP Framework ของคุณได้ เพื่อประหยัดเวลาในการหา function ฯลฯ</li><li>ก่อนลงมือเขียนจริง ควรสร้าง Class Diagram และ ER-Diagram ก่อน แต่ถ้าคุณไม่ถนัด เวลาทำงานเมื่อคุณสะกิดใจว่ามันผิดแปลก อย่าฝืนทำต่อแต่ต้องแก้ ให้เป็นไปอย่างที่มันควรจะเป็นซะ อย่าปล่อยปัญหาไว้</li><li>ถ้า Framework ไม่มี Unit Test มาให้ควรใช้พวก Unit Test ของตัวอื่นมาใช้ซะ เพื่อระบบที่มีคุณภาพ เช่น Firephp เป็นตัวหนึ่งที่ใช้ได้</li><li>หัดทำบ่อยๆจะได้ชิน และควรตั้งเป้าหมายให้มากขึ้น เช่น รองรับ i18n , การเปลี่ยน template ฯลฯ</li><li>ค้นหา plugin ต่างๆก่อนที่คิดจะสร้างขึ้นมา ไม่แน่ว่าจะได้งานที่ดีกว่า และประหยัดเวลากว่า</li></ol><p>วันนี้ก็ลากับ 10 ข้อง่ายๆสำหรับคนใช้ PHP MVC Framework นะครับ แต่ใช้ได้กับ Framework ตัวอื่นๆด้วยนะครับ โดยนี้คือความเห็นส่วนตัวของผมและงานที่ผมทำคือ Web Application ซึ่งมีอะไรมากมายจริงๆ</p> Similar Posts:<ul><li><a
href="http://www.dominixz.com/blog/productivity/exam-finished-return-of-dominixz/" rel="bookmark" title="July 27, 2007">สอบเสร็จแล้วครับ Return of the Dominixz</a></li><li><a
href="http://www.dominixz.com/blog/programming-solution/clean-tag-html-with-jquery/" rel="bookmark" title="July 19, 2008">ทำความสะอาด Tag Html ด้วย jQuery</a></li><li><a
href="http://www.dominixz.com/blog/life-talk/iywc6-experience/" rel="bookmark" title="October 20, 2008">เล่าสู่กันฟัง IYWC รุ่นที่ 6</a></li></ul>]]></content:encoded> <wfw:commentRss>http://www.dominixz.com/blog/programming-solution/suggest-solution-for-php-mvc-framework/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>เข้าใจกับ jQuery Ajax Cross Domain</title><link>http://www.dominixz.com/blog/programming-solution/understanding-jquery-ajax-cross-domain/</link> <comments>http://www.dominixz.com/blog/programming-solution/understanding-jquery-ajax-cross-domain/#comments</comments> <pubDate>Mon, 27 Apr 2009 09:04:53 +0000</pubDate> <dc:creator>DominixZ</dc:creator> <category><![CDATA[วิธีแก้ปัญหาเขียนโปรแกรม]]></category> <category><![CDATA[ajax]]></category> <category><![CDATA[cross domain]]></category> <category><![CDATA[jquery]]></category><guid
isPermaLink="false">http://www.dominixz.com/blog/?p=652</guid> <description><![CDATA[หลังจากที่ผมใช้ jQuery เป็น Javascript Framework หลักมาตลอดตอนนี้ ผมพึงได้ทำอะไรใหม่ๆ มากกว่าที่ผมทำอยู่เป็นประจำเช่น การทำ Web Service ที่ Javascript จะต้องเป็นคนเรียก วันนี้ผมก็พึุงได้รู้ว่าจริงๆแล้ว jQuery Ajax ไม่ได้โหลด Cross Domain ได้ทุก function หลังจากลอง Search ดูก็พึุงรู้ว่าจริงๆแล้วตอนนี้มีแค่ getJSON getScript $.ajax เท่านั้นที่ทำได้ โดย $.ajax ก็คือการ setup ให้ datatype เป็น JSONP  หรือไม่ก็ Script เท่านั้นถึงทำได้ ดังนั้นเวลาเรียกให้ควร check เรื่องพวกนี้เป็นพิเศษ เพราะการทำภายใต้ domain เดียวกันนั้น คุณสามารถใช้พวก $.get , $.post ได้ตามสะดวก แต่พอจะทำ cross domain แล้วนั้นกลับทำไม่ได้ [...]]]></description> <content:encoded><![CDATA[<p>หลังจากที่ผมใช้ jQuery เป็น Javascript Framework หลักมาตลอดตอนนี้ ผมพึงได้ทำอะไรใหม่ๆ มากกว่าที่ผมทำอยู่เป็นประจำเช่น การทำ Web Service ที่ Javascript จะต้องเป็นคนเรียก วันนี้ผมก็พึุงได้รู้ว่าจริงๆแล้ว jQuery Ajax ไม่ได้โหลด Cross Domain ได้ทุก function หลังจากลอง Search ดูก็พึุงรู้ว่าจริงๆแล้วตอนนี้มีแค่</p><ul><li>getJSON</li><li>getScript</li><li>$.ajax</li></ul><p>เท่านั้นที่ทำได้ โดย $.ajax ก็คือการ setup ให้ datatype เป็น JSONP  หรือไม่ก็ Script เท่านั้นถึงทำได้ ดังนั้นเวลาเรียกให้ควร check เรื่องพวกนี้เป็นพิเศษ เพราะการทำภายใต้ domain เดียวกันนั้น คุณสามารถใช้พวก $.get , $.post ได้ตามสะดวก แต่พอจะทำ cross domain แล้วนั้นกลับทำไม่ได้ ดังนั้น ถ้าคิดจะทำ Web Service ที่ Javascript สามารถเรียกได้ ควรทดสอบด้วย getJSON หรือ getScript เท่านั้นครับ</p><p>ส่วนถ้าใช้กับพวก Server Side Script จะมีวิธีที่เรียกว่า Proxy ซึ่งทำให้สะดวกในการทำงาน ซึ่งเราสามารถใช้ได้ทุก Ajax เช่น $.get $.post ก็ใช้ได้หมด โดยมีตัวอย่างที่ทำเข้าใจอย่างมากของฝรั่งเขา ดูได้ที่นี้เลยครับ<br
/> <a
href="http://jquery-howto.blogspot.com/2009/04/cross-domain-ajax-querying-with-jquery.html">http://jquery-howto.blogspot.com/2009/04/cross-domain-ajax-querying-with-jquery.html</a></p><p>ปล. สำหรับลิงค์ที่้ให้ไป อ่าน comment ด้วยจะได้เห็นทางเลือกที่เจ๋งๆอีกนิดหน่อย</p> Similar Posts:<ul><li><a
href="http://www.dominixz.com/blog/programming-solution/ajax-cross-domain-with-codeigniter-and-jquery/" rel="bookmark" title="March 6, 2009">วิธีทำ Ajax Cross Domain แบบสมบูรณ์ด้วย CodeIgniter และ jQuery</a></li><li><a
href="http://www.dominixz.com/blog/programming-solution/common-web-develop-problems-1/" rel="bookmark" title="March 27, 2009">ปัญหางานทั่วไปที่เจอในงานพัฒนาเว็บ (1)</a></li><li><a
href="http://www.dominixz.com/blog/review/web-development/codeigniter-jquery-extjs-adobe-air/" rel="bookmark" title="April 25, 2008">Codeigniter , jQuery , Ext-Js และ Adobe AIR</a></li></ul>]]></content:encoded> <wfw:commentRss>http://www.dominixz.com/blog/programming-solution/understanding-jquery-ajax-cross-domain/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>การขึ้นบรรทัดใหม่ของไฟล์ด้วย Ruby บน Windows</title><link>http://www.dominixz.com/blog/programming-solution/new-line-file-with-ruby-on-windows/</link> <comments>http://www.dominixz.com/blog/programming-solution/new-line-file-with-ruby-on-windows/#comments</comments> <pubDate>Fri, 17 Apr 2009 14:31:17 +0000</pubDate> <dc:creator>DominixZ</dc:creator> <category><![CDATA[วิธีแก้ปัญหาเขียนโปรแกรม]]></category><guid
isPermaLink="false">http://www.dominixz.com/blog/?p=643</guid> <description><![CDATA[วันนี้ด้วยการจะทำการจัดการกับ Textfile แต่ก็ติดปัญหาเล็กน้อยว่า ทำไมใช้ myfile.puts แล้วไม่มีการขึ้นบรรทัดใหม่ให้บน Windows ก็งงไปพักใหญ่ ใช้ print หรือ write ก็แล้วโดยใส่ \n แล้วก็ไม่ติด จนกระทั่งลองทำไฟล์ปกติขึ้นมาอันหนึ่งแล้ว ลองเอาไปเปิดดูใน Ruby ก็เห็นว่าเขาเขียนด้วย \r\n โดย \n จริงๆคือการขึ้นบรรทัดใหม่ ส่วน \r ก็คือ carriage return ซึ่งเป็นตัวอักษรตัวหนึ่งใน ASCII ซึ่งใน windows คงหมายถึงกด &#8220;enter&#8221; ดังนั้นวิธีแก้ปัญหาก็ค้นพบแล้วก็คือการใส่ \r\n เพื่อการขึ้นบรรทัดใหม่ โดยใช้กับคำสั่ง write หรือ print ก็ได้ (แต่ใช้กะ puts มะได้นะ) ตัวอย่างเช่น myfile = File.new(&#8220;test.txt&#8221;,&#8221;w&#8221;) 3.times { myfile.write(&#8220;hello\r\n&#8221;) } myfile.close ประมาณนี้เป็นต้น [...]]]></description> <content:encoded><![CDATA[<p>วันนี้ด้วยการจะทำการจัดการกับ Textfile แต่ก็ติดปัญหาเล็กน้อยว่า ทำไมใช้ myfile.puts แล้วไม่มีการขึ้นบรรทัดใหม่ให้บน Windows ก็งงไปพักใหญ่ ใช้ print หรือ write ก็แล้วโดยใส่ \n แล้วก็ไม่ติด จนกระทั่งลองทำไฟล์ปกติขึ้นมาอันหนึ่งแล้ว ลองเอาไปเปิดดูใน Ruby ก็เห็นว่าเขาเขียนด้วย \r\n โดย \n จริงๆคือการขึ้นบรรทัดใหม่ ส่วน \r ก็คือ <a
href="http://en.wikipedia.org/wiki/Carriage_return">carriage return</a> ซึ่งเป็นตัวอักษรตัวหนึ่งใน ASCII ซึ่งใน windows คงหมายถึงกด &#8220;enter&#8221; ดังนั้นวิธีแก้ปัญหาก็ค้นพบแล้วก็คือการใส่ \r\n เพื่อการขึ้นบรรทัดใหม่ โดยใช้กับคำสั่ง write หรือ print ก็ได้ (แต่ใช้กะ puts มะได้นะ)</p><p>ตัวอย่างเช่น<br
/> myfile = File.new(&#8220;test.txt&#8221;,&#8221;w&#8221;)<br
/> 3.times { myfile.write(&#8220;hello\r\n&#8221;) }<br
/> myfile.close</p><p>ประมาณนี้เป็นต้น ลองทำดูครับ <img
src='http://www.dominixz.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /></p> Similar Posts:<ul><li><a
href="http://www.dominixz.com/blog/productivity/ruby-problem-for-java-programmer/" rel="bookmark" title="August 5, 2008">ปัญหาของ Ruby ! สำหรับชาว Java</a></li><li><a
href="http://www.dominixz.com/blog/review/simply-rails-2/" rel="bookmark" title="September 15, 2008">Simply Rails 2 ~ Book Review ~</a></li><li><a
href="http://www.dominixz.com/blog/productivity/firefox-3-add-on-enter-selects/" rel="bookmark" title="September 5, 2008">Firefox 3 Add-on : Enter Selects</a></li></ul>]]></content:encoded> <wfw:commentRss>http://www.dominixz.com/blog/programming-solution/new-line-file-with-ruby-on-windows/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> </channel> </rss>
<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk: basic
Page Caching using disk: basic (User agent is rejected)
Database Caching using disk: basic

Served from: www.dominixz.com @ 2012-02-11 19:44:17 -->
