วันจันทร์ที่ 7 พฤศจิกายน พ.ศ. 2554

จากสวนผักสู่คลองมหาสวัสดิ์ปลายทางที่รติรมย์ 2 ตอนที่ 2



หลังจากการเดินทางร่วม 2 ชั่วโมง ต่อรถ 2 ทอด และมาต่อเรืออีกทอดจนมาถึงหน้าหมู่บ้านก็บ่ายโมงพอดี ผู้คนที่เคยสัญจรไปมาในหมู่บ้านไม่มีให้เห็นเหมือนปกติราวกับหมู่บ้านร้าง เข้าใจว่าคนในหมู่บ้านคงจะอพยพย้ายไปอยู่ที่อื่นกันเกือบหมด บ้านหลังหนึ่งเจ้าของบ้านเตรียมการป้องกันมาอย่างดีตั้งแต่น้ำยังไม่ท่วมสุดท้ายแล้วก็ต้องพ่ายแพ้ต่อภัยธรรมชาติเหมือนกับบ้านหลังอื่น ๆ ที่ไม่ได้เตรียมการอะไรเลยอย่างเท่าเทียมกัน สนามบาสหน้าสโมสรหมู่บ้านซึ่งเป็นที่สูงมีคนนำรถมาจอดหนีน้ำอยู่หลายคันแต่ก็หนีไม่พ้นต้องจมน้ำเช่นกัน

































เรือแล่นไปจนถึงเนินสะพานในหมู่บ้านก่อนที่จะข้ามไปยังเฟส 2 ก็ต้องลงเดินลุยน้ำไปอีกไม่กี่สิบเมตรก็จะถึงที่หมายแล้ว ก่อนลงเรือก็นัดแนะเวลากับลุงคนขับเรือให้มารับตามเวลาที่กำหนดแกบอกว่าไม่ต้องรีบร้อนเสร็จธุระเมื่อไรก็โทรเรียกได้ทันทีพร้อมกับบอกเบอร์โทรเสร็จสรรพ ส่วนค่าจ้างนั้นลุงใจดีบอกเอาไว้ค่อยให้ตอนขากลับก็ได้ ระดับน้ำในหมู่บ้านสูงระดับต้นขาเกือบ ๆ เอว กางเกงยางกันน้ำสีสันสดใสและรองเท้าบูตซึ่งขายดีเทน้ำเทท่าอยู่ในขณะนี้สามารถป้องกันน้ำเข้า... ได้เป็นอย่างดี ระหว่างทางที่เดินลุยน้ำอยู่นั้นมีอยู่ช่วงหนึ่งที่ไปสะดุดอะไรไม่รู้ใต้น้ำถึงกับสะดุ้งเพราะไม่รู้ว่าจระเข้ที่หลุดออกมาจะมาเพ่นพ่านแถวนี้หรือไม่ แต่อย่างไรก็ตามการเดินอยู่กลางน้ำที่เย็นฉ่ำท่ามกลางความเงียบเหงาเหมือนเราเป็นเจ้าของหมู่บ้านแห่งนี้เพียงคนเดียวเป็นบรรยากาศที่หาไม่ได้อีกแล้ว
























ในที่สุดก็มาถึงจุดหมายปลายทาง ระดับน้ำหน้าบ้านลดลงมาหน่อยอยู่ในระดับที่เลยเข่าเกือบ ๆ ต้นขา ก่อนหน้าที่น้ำจะเข้าท่วมหมู่บ้าน เคยพูดกันเล่น ๆ ว่าเทศการลอยกระทงปีนี้สงสัยจะได้ลอยกระทงกันหน้าบ้านไม่น่าเชื่อว่าในที่สุดจะเป็นจริงยิ่งกว่าคือลอยกันในบ้านได้เลย ร่องรอยของคราบน้ำชี้ให้เห็นถึงจุดที่น้ำขึ้นสูงสุดแตะระดับป้ายบ้านเลขที่(ไม่ได้ใบ้หวยนะ)พอดิบพอดี ต้นเข็มที่เคยออกดอกชูช่อใหญ่ให้ชื่นชมตลอดแนวหน้าบ้านออกอาการใบเหลืองเหี่ยวตายจากการจมอยู่ใต้น้ำเป็นเวลานาน


ก่อนที่จะเปิดประตูรั้วเข้าไปในบริเวณบ้าน เพื่อความไม่ประมาทก็ต้องตรวจเช็คไฟฟ้ารั่วเสียก่อนด้วยไขควงวัดกระแสไฟฟ้าที่เตรียมตัวมาเป็นอย่างดี และหวังว่าหากมีไฟฟ้ารั่วจริงกางเกงยางกันน้ำคงจะเอาอยู่ แผ่นไม้อัดที่นำมาทำเป็นพนังกั้นน้ำบริเวณชานพักหน้าประตูบ้านพร้อมกับซิลิโคนยาอย่างแน่นหนาก็มิอาจขวางกั้นน้องน้ำที่เข้ามาเยือนโดยไม่ได้รับเชิญได้


ระดับน้ำที่สูงไม่เกินคันกั้นน้ำที่ทำไว้ทำให้สามารถประเมินความเสียหายคร่าว ๆ ได้แม้ไม่ต้องเข้าไปในตัวบ้าน คาดเดาได้ว่าน้องน้ำน่าจะแอบตีท้ายครัวเข้ามาทางท่อระบายน้ำในห้องน้ำแล้วดันถุงทรายที่วางทับไว้จนเอ่อเข้าท่วมในบ้าน โชคดีที่พื้นบ้านอยู่สูงกว่าพื้นถนนอยู่ 2-3 ขั้นบันได ทำให้น้ำในบ้านไม่สูงมากนักเลยระดับขอบบัวมาอีกนิด ถือได้ว่าความเสียหายไม่ได้รุนแรงอย่างที่คาดไว้


ระดับน้ำที่ยังลดลงไม่มากนักทำให้เราตัดสินใจที่จะไม่เปิดประตูบ้านเข้าไปสำรวจความเสียหายภายในเพราะเกรงว่าประตูซึ่งทำด้วยไม้แช่น้ำอยู่นานอาจจะบวมไม่สามารถปิดคืนได้เหมือนเดิม เราจึงมองลอดเข้าไปในตัวบ้าน โซฟาผ้านุ่ม ๆ ที่เคยนั่งแสนอุ่นสบายมาบัดนี้ได้ถูกน้องน้ำล้อมจับไว้เป็นตัวประกันเป็นที่เรียบร้อย ตู้เย็นซึ่งถูกห่อด้วยผ้าใบในระดับที่ไม่สูงมากนักหวังว่าจะช่วยให้รอดพ้นจากน้ำเข้าเครื่องได้


สวนข้างบ้านที่เคยนั่งเล่นกินลมได้กลายสภาพเป็นสวนน้ำขนาดใหญ่ดูดีไปอีกแบบ เสียดายไม่มีปลาคราฟสวย ๆ ว่ายเวียนวนให้เพลิดเพลินใจ







อีกมุมหนึ่งของบ้าน ม้านั่งหินอ่อนจมอยู่ใต้น้ำ












พืชน้ำขนาดเล็กจำพวกจอกแหนตะไคร่น้ำเจริญงอกงามสีเขียวสดใส





















ปั๊มน้ำหลังบ้านชุ่มโชกไปด้วยน้องน้ำ














ท่ามกลางความสูญเสียยังมีอีกมุมหนึ่งที่สอดแทรกด้วยความงดงามที่ไม่ได้ถูกทำลายไปกับสายน้ำพอให้ชื่นใจได้บ้าง








น้ำจะสูงแค่ไหนก็ไม่เป็นอุปสรรคของดอกบัวที่จะโผล่พ้นน้ำมาอวดความสวยงาม





เวลาก็เริ่มบ่ายคล้อยแล้วจึงจำเป็นต้องเดินทางกลับก่อนที่ตะวันจะตกดิน จึงได้โทรนัดให้เรือมารับตามเวลาและตั้งใจว่าจะเดินลุยออกไปรอเรือหน้าหมู่บ้านเพื่อวัดระดับน้ำ เดินลุยไปได้ครึ่งทางก็ต้องล้มเลิกความตั้งใจ จนกระทั่งเรือมารับพอดี ขากลับลุงแกไปส่งถึงถนนใหญ่ตรงแยกราชพฤกษ์โดยไม่ต้องผ่านถนนสวนผักซึ่งจะมีรถใหญ่วิ่งเยอะกว่า ก่อนลงจากเรือก็ควักเงินให้แกไป 200 บาทเพื่อเป็นค่าจ้างสินน้ำใจสำหรับการบริการด้วยน้ำใจไมตรีที่มีต่อเพื่อนมนุษย์ยามตกทุกข์ได้ยาก นั่นคือบันทึกการเดินทางของคนคนหนึ่งที่ต้องประสพกับชะตากรรมจากภัยธรรมชาติเหมือนกับใครอีกหลาย ๆ คน ซึ่งสอนให้เรารู้ว่ามนุษย์เราได้ทำลายธรรมชาติมามากแล้วและขณะนี้มันกำลังเอาคืน

วันอาทิตย์ที่ 6 พฤศจิกายน พ.ศ. 2554

จากสวนผักสู่คลองมหาสวัสดิ์ปลายทางที่รติรมย์ 2 ตอนที่ 1

ตั้งแต่อพยพออกจากบ้านมาได้ 2 สัปดาห์ก่อนหน้าที่น้ำจะเข้าท่วมหมู่บ้านอย่างหนักจนกระทั่งถึงวันนี้ก็ยังไม่ทราบชะตากรรมเลยว่าน้ำจะเข้าบ้านสร้างความเสียหายไปขนาดไหน ได้ยินข่าวเกี่ยวกับน้ำท่วมเขตตลิ่งชันอย่างหนัก ถนนสวนผักซึ่งอยู่ในเขตนี้ก็หนีไม่พ้นถูกน้ำท่วมเช่นกันเนื่องจากถนนสายนี้เป็นถนนเลียบคลองมหาสวัสดิ์ซึ่งเป็นคลองที่ปรากฏเป็นข่าวอยู่ทุกวันเพราะต้องรับเอามวลน้ำที่อยู่ทางตอนบนเข้ามาเต็ม ๆ ความกังวลเริ่มเกิดขึ้นเพราะไม่รู้ว่าระดับน้ำจะสูงแค่ไหน น้ำจะเข้าบ้านหรือไม่ ข่าวการเสียชีวิตของชาวบ้านที่ถูกไฟฟ้าช็อตจนเสียชีวิต ถูกจระเข้กัด หรืองูเขียวแมมบ้าซึ่งมีพิษร้ายหลุดออกมาแถวนนทบุรี ประกอบกับน้ำซึ่งท่วมอยู่นานและเริ่มสกปรกส่งกลิ่นเน่าเหม็นแล้ว ทำให้ความคิดที่จะหาทางเข้าไปดูบ้านต้องล้มเลิกไปหลายครั้ง


ด้วยความอยากรู้ว่าน้ำจะเข้าบ้านเท่าไร เสียหายมากขนาดไหน จึงได้รวบรวมความกล้าลุยน้ำเข้าไปดูในวันนี้ให้ได้ โดยเริ่มจากขับรถไปตามถนนราชพฤกษ์จนไปถึงจุดที่ไปต่อไม่ได้บริเวณแยกบรมราชชนนีซึ่งเริ่มมีน้ำท่วมขังรถเล็กผ่านไม่ได้แล้ว ตลอดทางจะเห็นรถจอดเรียงรายอยู่ริมถนนซ้อน 2 บ้างซ้อน 3 บ้าง มีการขับรถย้อนศรวุ่นวายกันเต็มไปหมด จากนี้ต่อไปก็ต้องโบกรถใหญ่ลุยต่อไปทางถนนสวนผักซึ่งมีรถทหารคอยให้บริการอยู่แล้วแต่กว่าจะมาแต่ละคันก็ช้ามาก โชคดีที่มีรถกระบะใจดีผ่านมาและจะไปสวนผักอยู่พอดีจึงได้อาศัยนั่งกระบะท้ายท่ามกลางแสงแดดอันร้อนระอุ












ตลอดสายถนนสวนผักตั้งแต่แยกราชพฤกษ์เข้ามาถึงตลาดกรุงนนท์ปากซอยสวนผัก 32 จมอยู่ใต้บาดาล ระดับน้ำประมาณครึ่งหน้าแข้ง บริเวณตลาดหน้าปากซอยมีชาวบ้านนำของมาขายกันอย่างคึกคักจะเรียกว่าตลาดน้ำก็ไม่ผิด


หลังจากขอบอกขอบใจคนขับรถกระบะก็ต้องลุยต่อด้วยการข้ามสะพานนี้ไป พ้นสะพานก็เข้าเขตนนท์พอดี แต่วันนี้เราจะเปลี่ยนวิธีเดินทางด้วยการล่องเรือไปตามคลองนี้แทน เจ้าคลองมหาสวัสดิ์นี่แหละคือตัวปัญหาที่ทำให้น้ำท่วมในบริเวณนี้เป็นวงกว้าง อยู่แถวนี้มาหลายปีก็มีวันนี้แหละที่ได้มีโอกาสสำรวจคลองอย่างจริงจัง คำแนะนำจากลุงใจดีคนหนึ่งซึ่งเป็นชาวบ้านในแถบนี้บอกว่าหากเดินข้ามสะพานไปขึ้นเรือที่ฝั่งกระโน้นจะถูกโขกค่าเรืออย่างแพงเพราะมีพวกมาเฟียมาคอยกินหัวคิว(คอยซ้ำเติมผู้ที่เดือดร้อน) แกบอกว่าฝั่งนี้จะมีชาวบ้านที่มีเรือมาคอยบริการให้ส่วนค่าบริการนั้นก็แล้วแต่จะให้ตามกำลังทรัพย์


สิ่งที่สังเกตเห็นได้ชัดคือเรือของชาวบ้านส่วนใหญ่จะเป็นเรือเก่า ๆ ที่ทำด้วยไม้นำมาติดเครื่องยนต์ เรือที่กำลังนั่งอยู่นี้ลุงเจ้าของเรือคุยโวว่าเรือลำนี้อายุร่วม 100 ปีได้ น้ำซึ่งรั่วซึมเข้ามานองพื้นเรือจนต้องคอยวิดออกเป็นระยะ ๆ เป็นสิ่งที่พิสูจน์คำพูดของแกได้เป็นอย่างดี ตลอดทางสองฝั่งคลองเต็มไปด้วยน้ำเวิ้งว้างไปหมด น้ำสูงเอ่อล้นจนมองไม่เห็นแม้แต่ริมสันเขื่อนที่สร้างให้สูงขึ้นหลังจากน้ำท่วมปี 38 จนมองไม่ออกเลยว่าชาวบ้านที่อาศัยอยู่ริมคลองจะอาศัยกันอยู่ได้อย่างไร

















ตลอดระหว่างทางลุงคนขับเรือเล่าให้ฟังว่าน้ำปีนี้มหาศาลมาก เขตเทศบาลพยายามสู้แต่ก็สู้ไม่ไหวจริง ๆ พร้อมกับชี้จุดให้เห็นร่องรอยของเขื่อนริมคลองที่พังอยู่หลายจุด หลังจากล่องเรือมาได้ซัก 15 นาที ลุงแกก็พาเรือลัดเลาะมาทางข้างโรงงานริมคลองซึ่งก่อนหน้านี้เป็นทางลาดซีเมนต์ให้รถเข้าออกได้แต่บัดนี้ได้กลายเป็นคลองย่อยใช้เป็นทางลัดตัดเข้าสู่ถนนจงถนอม-ปลายบางซึ่งเป็นทางเข้าหมู่บ้านไปโดยปริยาย



และแล้วก็มาถึงซะทีหมู่บ้านรติรมย์ 2 หลังจากใช้เวลาเดินทางเกือบ 2 ชั่วโมง เห็นระดับน้ำหน้าหมู่บ้านประมาณระดับอกก็เตรียมทำใจได้เลย ลุงแกก็ไม่รอช้ารีบหันหัวเรือเข้าหมู่บ้านในทันทีพร้อมกับบอกว่าจะบริการส่งให้ถึงหัวกระไดบ้านเลย ตลอดทางเข้าในหมู่บ้านอันร่มรื่น มาบัดนี้ได้กลายเป็นคลองที่สวยสดงดงาม บ้านแต่ละหลังได้กลายเป็นบ้านสวนริมน้ำอันอุดมสมบูรณ์สมกับชื่อถนน(สวนผัก)




โปรดติดตามตอน 2 ไปวัดระดับน้ำในบ้านกัน

วันจันทร์ที่ 21 มีนาคม พ.ศ. 2554

ดึงข้อมูลจากเว็บโดยอัตโนมัติด้วย PL/SQL

หลายครั้งที่ผมมีความจำเป็นต้องดึงข้อมูลจากหน้าเว็บบางเว็บเข้ามาเก็บในฐานข้อมูล เลยต้องมาคิดหาวิธีว่าจะทำอย่างไรที่จะดึงข้อมูลมาได้อย่างรวดเร็วที่สุดนอกจากวิธีแบบลูกทุ่งเลยก็คือการไปที่หน้าเว็บนั้น ๆ แล้วก็ทำการ Copy&Paste ซึ่งก็จะเสียเวลาทำมาหากินนานมาก ยิ่งถ้ามีจำนวนข้อมูลมาก ๆ แล้วไม่ต้องพูดถึง

โชคดีที่ภาษา PL/SQL ของ Oracle มีฟังก์ชันที่ช่วยให้เราสามารถดึงข้อมูลจากเว็บได้อย่างรวดเร็วโดยอัตโนมัติ โดยฟังก์ชันเหล่านี้จะอยู่ในแพ็คเก็จ UTL_HTTP ซึ่งมากับ Database อยู่แล้ว ดังนั้นตัวอย่างนี้จะแสดงให้เห็นถึงการดึงข้อมูลจากเว็บอย่างง่าย ๆ ตามมาเลยครับ






ตัวอย่างนี้จะเป็นการดึงข้อมูลจากเว็บ http://www.w3schools.com/xpath/books.xml ซึ่งเป็นข้อมูลที่อยู่ในรูปแบบ XML แสดงรายชื่อหนังสือ โดยเริ่มจากใส่ค่า URL Address ของเว็บที่เราต้องการเข้าไปที่ตัวแปร UTL_HTTP.begin_request หลังจากนั้นคำสั่ง UTL_HTTP.read_text จะทำการอ่านข้อมูลมาเก็บลงในตัวแปร text ซึ่งกำหนดไว้เป็น VARCHAR2 ขนาด 32760 ไบต์ หลังจากนั้นจึงทำการแสดงผลลัพธ์ที่อยู่ในตัวแปร text ด้วยคำสั่ง DBMS_OUTPUT.put_line ออกมาทางจอภาพ ดังรูป




ถึงตรงนี้เราสามารถที่จะจัดการกับข้อมูลต่อได้โดยอาจจะใช้ฟังก์ชัน substr เพื่อตัดข้อความตรงตำแหน่งที่ต้องการเพื่อให้ได้ข้อมูลตามต้องการ ด้วยตัวอย่างโค้ดสั้น ๆ ง่าย ๆ เพียงเท่านี้เราก็สามารถดึงข้อมูลจากเว็บมาใช้งานได้ แต่ตัวอย่างนี้ก็ยังมีข้อจำกัดอยู่เนื่องจากตัวแปร text จะเก็บข้อมูลได้เพียง 32760 ไบต์เท่านั้น ดังนั้นหากข้อมูล html source ที่ได้จากเว็บมีขนาดข้อมูลมากกว่าตัวแปร text จะรับได้ก็จะเกิด error ขึ้น

วันเสาร์ที่ 24 กรกฎาคม พ.ศ. 2553

จัดการกับ Comm Port ด้วย Oracle Forms 6i









หลายคนคงจะเข้าใจว่าเครื่องมือในการพัฒนาโปรแกรมของ Oracle อย่าง Form Builder คงจะเก่งแต่การจัดการกับข้อมูลในฐานข้อมูล ส่วนเรื่องที่จะเอาเครื่องมือนี้ไปพัฒนาโปรแกรมที่จะต้องติดต่อสื่อสาร (Communicate) กับ Hardware อื่น ๆ ผ่านทาง Communication Port หรือ Serial Port คงจะทำไม่ได้ หลายคนก็เลยเปลี่ยนใจไปใช้ Tools อื่น ๆ พัฒนาแทน เพราะมีบาง Application ที่จะต้องคุยกับ Hardware อื่น ๆ เช่น โปรแกรมระบบงานขายสดอย่าง Point of Sales (POS) ซึ่งจะต้องต่อเชื่อมกับป้าย Display เพื่อแสดงราคาให้ลูกค้าเห็น โดยที่ป้าย Display นี้จะเป็นอุปกรณ์ Hardware ตัวหนึ่งที่ต่อเชื่อมกับเครื่อง PC ผ่านทาง Serial Port

บทความนี้จะมาช่วยไขข้อข้องใจให้กับหลาย ๆ คนได้เกี่ยวกับการใช้ Oracle Foms ติดต่อสื่อสารและส่งข้อมูลผ่านทาง Communication Port หรือ Serial Port โดยในที่นี้จะกล่าวถึงการพัฒนาด้วย Oracle Forms Version 6i โชคดีที่ Oracle Forms ได้เตรียมเครื่องมือ OLE Container มาให้ เราจะมาทดลองเขียนโปรแกรมส่งข้อมูลไปยัง Comm Port ได้ดังนี้


1. สร้าง Form ใหม่ขึ้นมา แล้วเปิด Canvas จากนั้นที่แถบเครื่องมือด้านซ้าย (Tools Palette) ให้คลิกเลือกเครื่องมือ OLE Container แล้วนำมาวางใน Canvas คลิกขวาที่ Object นั้นแล้วเลือก Insert Object จะปรากฏ Insert Object Dialog Box ขึ้นมาให้คลิก Create Control และในช่อง Control Type เลือก Microsoft Comunications Control แล้วคลิก OK

2. ถึงตรงนี้ถ้าไม่มีอะไรผิดพลาดเราจะเห็น OLE Object ที่เราสร้างขึ้นเป็นรูปโทรศัพท์ ต่อไปเราจะมาสร้างปุ่ม Comm Port Test โดยผลลัพธ์จากการกดปุ่มจะเป็นการสั่งให้โปรแกรมส่ง Output ที่เป็นตัวอักษรไปยัง Communication Port ซึ่งในที่นี้เราจะทดสอบกับพอร์ต Comm1 โดยเขียนโค้ดใน When-Button-Pressed Trigger ดังนี้


หลังจากเขียนโค้ดเสร็จก็ลอง run โปรแกรม โดยถ้าจะให้เห็นภาพมากขึ้นก็อาจจะต้องมีอุปกรณ์ที่เป็น Hardware มาต่อเชื่อมที่พอร์ต Comm1 ของเครื่อง PC เช่นป้าย Display หรืออาจจะเป็นเครื่องพิมพ์ชนิดที่ต่อผ่าน Comm Port ก็จะเห็นผลลัพธ์นั้นแสดงออกมา หวังว่าบทความนี้คงจะเป็นแนวทางในการนำไปเขียนโปรแกรมที่ใช้สื่อสารกับอุปกรณ์อื่น ๆ ผ่านทาง Communication Port ได้บ้างไม่มากก็น้อยนะครับ






วันศุกร์ที่ 30 ตุลาคม พ.ศ. 2552

จัดการกับ index ที่ไม่ได้ใช้งาน

การทำ index ให้กับ Table จะช่วยให้การสืบค้นข้อมูลในฐานข้อมูลทำได้รวดเร็วขึ้นเนื่องจากระบบไม่ต้องไป scan หาข้อมูลที่ต้องการทั้ง Table แต่ก็ต้องแลกกับการสิ้นเปลืองเนื้อที่จัดเก็บ index มากขึ้นและระบบก็ต้องเสียเวลาบางส่วนไปกับการสร้างข้อมูลใน index ทุกครั้งเมื่อมีการปรับปรุงข้อมูลใน Table นั้น ๆ ใน ฐานข้อมูลขนาดใหญ่ที่มีการใช้งานมานานอาจจะมี index ที่ถูกสร้างไว้มากมาย index บางตัวอาจจะถูกสร้างมาใช้งานเพียงแค่ครั้งเดียวแล้วก็เลิกใช้ หรือบางตัวอาจจะไม่เคยถูกเรียกใช้งานเลย index เหล่านี้มีส่วนทำให้ performance ของระบบแย่ลงทั้ง ๆ ที่ไม่ได้มีความจำเป็นที่จะใช้ประโยชน์จาก index เหล่านี้เลย ดังนั้น index ที่ไม่จำเป็นและไม่ถูกใช้งานแล้วจำเป็นต้องลบทิ้งเพื่อไม่ให้เป็นขยะสิ้นเปลืองอยู่ในระบบ ทีนี้แล้วเราจะรู้ได้อย่างไรว่า index ตัวไหนถูกใช้งานหรือไม่มีการใช้งานแล้ว

ในออราเคิลเราสามารถดูได้ว่า index ตัวไหนไม่ได้ถูกใช้งานแล้วโดยเราจะต้องสั่งให้ระบบเริ่มเก็บสถิติการใช้งานเสียก่อนดังนี้

alter index index_name monitoring usage;

เมื่อ run คำสั่งนี้แล้วระบบจึงจะเริ่มเก็บข้อมูลเกี่ยวกับการใช้งาน index ที่ปรากฏอยู่ในคำสั่ง โดยเราสามารถดูผลได้จากวิว v$object_usage ซึ่งวิวนี้จะแสดงข้อมูลต่าง ๆ ดังนี้

Index_name -ชื่อ index
Table_name -ชื่อ Table ที่ทำ index
Monitoring -Yes/No เพื่อบอกว่ามีการเก็บสถิติ
Used -Yes/No เพื่อบอกว่า index มีการใช้งานหรือไม่
Start_monitoring -วันที่เริ่มเก็บสถิติ
End_monitoring -วันที่สิ้นสุดการเก็บสถิติ

ข้อมูลที่ได้จากวิวนี้จะบอกเราได้ว่า index ตัวใดไม่มีการใช้งานในช่วงเวลาที่เราเก็บสถิติโดยดูที่คอลัมน์ Used ถ้ามีค่าเป็น No ก็แสดงว่าไม่มีการใช้งาน ทีนี้เราก็สามารถลบ index ทิ้งได้เลย และหลังจากที่เราไม่ต้องการให้ระบบเก็บสถิติต่อไปเราก็ทำการยกเลิกได้โดยคำสั่งดังนี้

alter index index_name nomonitoring usage;

วันพุธที่ 21 ตุลาคม พ.ศ. 2552

ความสำคัญของ ROWID

เคยคิดมั้ยครับว่าการที่เรา query เพื่อต้องการข้อมูลซัก 1 row ใน table ตามเงื่อนไขที่เราต้องการนั้น ตัวออราเคิลเองมันทำงานอย่างไรถึงสามารถดึงข้อมูลมาให้เราได้อย่างรวดเร็วภายในพริบตา ถึงแม้ว่าใน database เราจะมีข้อมูลอยู่เป็นล้าน ๆ เรคคอร์ดก็ตาม การที่ออราเคิลทำอย่างนี้ได้แสดงว่าในแต่ละ row จะต้องมีการเก็บตำแหน่งเพื่อบอกว่า row นั้น ๆ อยู่ตรงไหนใน database เพื่อให้เข้าถึงข้อมูล row นั้น ๆ ได้โดยสะดวก เปรียบเสมือนกับเวลาที่เราต้องการค้นหาคำ ๆ หนึ่งในหนังสือ เราก็มักจะเปิดไปที่หน้าดัชนีซึ่งอยู่ท้ายเล่มเพื่อหาว่าคำที่ต้องการอยู่ในหน้าที่เท่าไรของหนังสือเล่มนั้น ออราเคิลเรียกตัวระบุตำแหน่งของ row นี้ว่า ROWID

ROWID ในความหมายของออราเคิลก็คือ pseudocolumn(คอลัมน์สมมุติ) เพื่อใช้บอกถึงตำแหน่งทาง physical ของข้อมูลแต่ละ row ใน table ว่าอยู่ที่ data file อะไร บล็อกไหนและอยู่ที่ row ที่เท่าไรใน data block โดยที่ค่าของ ROWID นี้จะเป็นค่า unique สำหรับแต่ละ row ใน table ที่ไม่ซ้ำกันเลย เราสามารถดูค่าของ ROWID ได้ด้วยคำสั่งดังนี้

SQL> select rowid from table_name;

ROWID
------------------
AAANUqAAGAAAVM2AAA
AAANUqAAGAAAVM2AAB
AAANUqAAGAAAVM2AAC
AAANUqAAGAAAVM2AAE

ค่าของ ROWID ที่แสดงให้เราเห็นนั้นถูกเก็บแบบเข้ารหัส BASE64 มีขนาดเท่ากับ 18 character โดยเราสามารถใช้ฟังก์ชัน DBMS_ROWID เพื่อแปลความหมายของ ROWID ได้ดังนี้

เก็บอยู่ที่ Table อะไร
select object_name from dba_objects where data_object_id = dbms_rowid.rowid_object('AAANUqAAGAAAVM2AAA')

เก็บอยู่ที่ Data file อะไร
select file_name from dba_data_files where file_id = dbms_rowid.rowid_relative_fno('AAANUqAAGAAAVM2AAA')

เก็บอยู่ที่ block ที่เท่าไร
select dbms_rowid.rowid_block_number('AAANUqAAGAAAVM2AAA') from dual

หาว่าอยู่ row ที่เท่าไร
select dbms_rowid.rowid_row_number('AAANUqAAGAAAVM2AAA') from dual

เมื่อเราเข้าใจกลไกการทำงานของ ROWID แล้วจะทำให้เราสามารถประยุกต์ใช้กับงานได้หลากหลายรูปแบบซึ่งเป็นสิ่งจำเป็นสำหรับผู้ดูแลระบบฐานข้อมูลออราเคิลที่จะต้องทำความเข้าใจถึงกลไกการทำงานในเชิงลึกก็จะทำให้การจัดการและดูแลระบบสะดวกรวดเร็วมากขึ้น ในที่นี้จะขอยกตัวอย่างหนึ่งที่เป็นการประยุกต์ใช้ประโยชน์ของ ROWID ในกรณีที่มีความต้องการจะลบข้อมูลที่มีซ้ำ ๆ กันหลาย ๆ row ใน table เดียวกันเพื่อให้เหลือเพียง row เดียว เราก็สามารถเขียน sql ได้ดังนี้

delete from table_name a where exists (select 1 from table_name b where a.COL1 = b.COL1 and b.ROWID < a.ROWID)

วันพฤหัสบดีที่ 8 ตุลาคม พ.ศ. 2552

วิธีคำนวณขนาดของ Table Sizes

ในการดูแลจัดการฐานข้อมูลออราเคิล สิ่งสำคัญที่ผู้ดูแลระบบ (DBA) จะต้องคำนึงถึงคือปริมาณของข้อมูลที่โตขึ้นเรื่อย ๆ ทุกวัน เพื่อจะได้ทำการวางแผน Purge ข้อมูลหรือหาซื้อ Disk มาเพิ่ม วิธีการคร่าว ๆ ที่จะหาขนาดของข้อมูลในแต่ละ Table นั้นก็อาจจะหาได้จาก เอาจำนวน Row ทั้งหมดใน Table คูณด้วยขนาดของ Data Type ในแต่ละ Column รวมกัน ซึ่งค่าที่คำนวณได้อาจจะไม่ตรงกับความเป็นจริงเนื่องจากออราเคิลเก็บข้อมูลแบบ Variable Length และที่สำคัญวิธีนี้ค่อนข้างจะกิน resource สูงและจะทำให้ performance ของระบบตกลงเนื่องจากออราเคิลจะเสียเวลาไปกับการ Scan ทั้ง Table เพื่อให้ได้จำนวน Row

วิธีการง่าย ๆ ที่ดีกว่าที่กล่าวมาซึ่งออราเคิลได้จัดเตรียมไว้ให้แล้วสามารถทำได้โดยใช้ View ที่ชื่อว่า DBA_SEGMENT โดยสั่ง run คำสั่งดังนี้

select byte from dba_segment where segment_name = 'table_name';

คำสั่งนี้จะได้ผลลัพธ์ขนาดของ Table เป็นจำนวน byte โดยระบุเงื่อนไข where เป็นชื่อของ Table ได้ตามต้องการ และในทำนองเดียวกันเราก็สามารถหาขนาดของ database segment อื่น ๆ ได้เช่นกัน เช่น Index หรือ Materialized View เป็นต้น