Query ที่ใช้งานบ่อยๆสำหรับทำ ETL , Data Warehouse และ Data Science ตอนที่ 1

สายงานดึงข้อมูลเพื่อใช้สำหรับวิเคราะห์ข้อมูล แปลงข้อมูล จัดรูปแบบข้อมูลต่างๆไม่ว่าวัตถุประสงค์ที่จะทำ ETL, Data warehouse , Data Science, Data Lake สิ่งที่จะเกิดขึ้นบ่อยๆคือ การจัดกลุ่มข้อมูล ROW_NUMBER(), RANK(), DENSE_RANK() การแปลงข้อมูล CAST,CASE การสร้าง View, Sub Table, temp table, Material View ,select ซ้อน select หลายชั้น (with) การทำงานด้านนี้จะแตกต่างจากการดึงข้อมูลในการทำงานแบบ CRUD (Create, Read, Update, Delete) เป็นงาน Transaction เน้นการทำงานที่เร็วอย่างมีประสิทธิภาพ ส่วนการวิเคราะห์ข้อมูลลืมเรื่อง Performance ไปได้เลยส่วนใหญ่คำสั่งที่ทาง Transaction Performance ต้องการให้เราหลีกเลี่ยงเราก็จะได้นำมาใช้งานอยากสนุกสนาน เนื่องจากตอนนี้ผมดึงข้อมูลจาก Oracle Database เป็นหลักก็เลยขอเขียนตัวอย่างของ Oracle ก่อนนะครับ ต่อไปค่อยเพิ่มเติม Database อื่นๆต่อไป การจัดกลุ่มข้อมูล พื้นฐานสุดๆที่รู้ๆกันคือการทำด้วยคำสั่ง Group By เช่นถ้าเราต้องการค่าเดียวจากตารางเลย select sum(a) from table_a แบบนี้ก็จะเป็นการ Group ข้อมูลทั้งตารางถ้าต้องการมีตัวแยกข้อมูลก็จะเป็น select column_a,count(*) from table_a group by column_a แบบนี้ก็จะมีตัวช่วยแบ่งกลุ่มข้อมูลออกมาแล้ว แต่การทำงานจริงไม่ได้ง่ายดายขนาดนั้น เช่น โจทย์ต้องการเอาค่าที่มากสุด น้อยสุดหรือล่าสุดของข้อมูลในตารางโดยต้องแบ่งข้อมูลออกเป็นส่วนๆตามที่ต้องการก่อน อันนี้ก็จะพอไหว แต่ถ้าบอกว่าต้องการเอาข้อมูลลำดับที่ 1 และลำดับที่ 2 ของข้อมูลมาเปรียบเทียบกันซึ่งไม่สนใจลำดับอื่นๆแบบนี้การแบ่งกลุ่มก็ต้องมาการจัดลำดับ และสามารถดึงลำดับที่ต้องการออกมาได้ อันนี้ยากแล้วเราก็ต้องมาดูว่าฐานข้อมูลแต่ละแบบมีตัวช่วยอะไรให้เราใช้บ้างในส่วนของ oracle จะมีฟังก์ชันกลุ่มนึงที่เป็นการเรียงลำดับข้อมูลนั่นก็คือ ROW_NUMBER(),  RANK(), DENSE_RANK()  ROW_NUMBER() ใช้สำหรับแป๊ะเลขที่ ของชุดข้อมูลที่สนใจ ถ้าไม่ Partition ข้อมูลก็จะเป็นการ แป๊ะเลขที่ของข้อมูลทั้งหมด ซึ่งใน Oracle จะมี อีกตัวไว้ใช้งานอยู่แล้วคือ ROWNUM ซึ่งเป็น pseudocolumn ไม่ต้องใช้ ROW_NUMBER() แต่ถ้าต้องการแบ่งข้อมูลออกเป็นส่วนๆด้วย ก็ต้องใช้ ROW_NUMBER บวกกับ PARTITION BY ลองดูตัวอย่างการทำงานจริงๆครับกว่าจะได้คำตอบมาต้องทำกี่ขั้นดังนี้ จากรูปอธิบายได้ดังนี้ RANK() ลักษณะการทำงานก็จะเหมือนตัวอย่าง ROW_NUMBER() จะเขียนอธิบายเฉพาะที่แตกต่างกันเท่านั้นดังนี้เป็นการแป๊ะตัวเลขลำดับให้กับชุดข้อมูลเดียวกัน แต่ค่าข้อมูลที่สนใจได้ลำดับเดียวกัน จะข้ามตัวเลขลำดับถันไปเท่ากับจำนวนลำดับที่เท่ากัน ดังรูปผลของ Query ด้านล่าง จากลำดับที่ 2 ไป 3 rows แล้วจะไปขึ้นลำดับที่ 5 เลย DENSE_RANK() จะเหมือนกัน RANK() แต่จะไม่มีการเว้นเลขลำดับ จะมีเลขที่ต่อเนื่องไปเลย ดังรูปผลของ Query ด้านล่าง จากลำดับที่ 2 ไป 3 rows แล้วจะต่อลำดับที่ 3 ต่อไป การแปลงข้อมูล CAST ใช้เพื่อแปลงชนิดของข้อมูลให้เป็นไปตามที่ต้องการ เช่น แปลงวันที่เป็นข้อความ กำหนดชนิดของข้อมูล Column ที่ยังไม่มีข้อมูลให้เป็นไปตามที่ต้องการ ดังตัวอย่าง CASE ใช้เพื่อจัดการข้อมูลในหลายๆรูปแบบเป็นการกำหนดเงื่อนไขขึ้นมาเพื่อแปลงข้อมูล ดังตัวอย่าง ต้องการ Update Column ให้มีค่าแตกต่างกันให้เป็นไปตามเงื่อนไขที่กำหนด การสร้าง VIEW, Temporary Table, Materialized view การแยกข้อมูลออกเป็นกลุ่มๆอีกวิธีที่ใช้งานเยอะคือการสร้าง View, Temporary Table, Materialized view View มีการเปลี่ยนแปลงตาม Table ต้นทาง View ไม่น่าจะต้องพูดเยอะเพราะน่าจะใช้งานกันเป็นประจำอยู่แล้ว Materialized view เป็นตารางที่มีข้อมูลที่ได้มาจากผลของการ Run Query ที่เราต้องการและมีการ Refresh ข้อมูลตามเวลาที่กำหนดไว้ ที่แตกต่างจาก View คือต้องการที่จัดเก็บข้อมูลส่วนตัวนะครับ ตัวอย่างการสร้าง Materialized View Temporary Table Temporary

Read More »

กำหนด Lexer สำหรับ Full Text Search บน ฐานข้อมูล Oracle เพื่อค้นหาภาษาไทยให้ถูกต้อง

เนื่องจากระบบสืบค้นที่ดูแลอยู่เจอปัญหาค้นหาเลขไทย “๑ ๒ ๓ …” ไม่เจอ หลังจากตรวจสอบจนแน่ใจแล้วว่าก่อนจะส่งคำสั่ง Query ไปยังฐานข้อมูลไม่ได้เผลอตัดเลขไทยออกที่ขั้นตอนไหน จึงทำการตรวจสอบคำสั่งที่ใช้ในการค้นหา พบว่าใช้ฟังก์ชัน SELECT * FROM THAI_LIBRARY WHERE CONTAINS(BOOK_NAME, ‘๑๐๐ ปีชาติไทย’, 1) > 0; จากคำสั่ง (ที่สมมุติขึ้น) ด้านบนจะเห็นได้ว่าใช้ CONTAINS ซึ่งเป็นฟังก์ชันที่อยู่ในกลุ่ม Oracle Text ซึ่งฟังก์ชันนี้จะค้นหาคำใกล้เคียงจาก Index แล้วคืนค่า Score มาให้เราเพื่อใช้เป็นเงื่อนไขพิจารณาว่าจะใช้ข้อมูลรายการนั้นหรือไม่ ที่มาภาพ ภาพด้านบนแสดงขั้นตอนการสร้าง Oracle Text Index เนื่องจากระบบจัดเก็บข้อมูลเป็น Text อยู่แล้วจึงไม่มีการกำหนด Fillter, Sectioner ทำให้จุดที่ต้องตรวจสอบว่า เลขไทยเราหายไปจาก Index ได้ยังไงเหลืออยู่คือ Lexer ที่จะเป็นตัวกำหนด Wordlist, Stoplist ในการทำ Index ต่อไป ไปดูว่ามี Lexer อะไรบ้าง จากตารางด้านบน เนื่องจากฐานข้อมูลของระบบที่ดูแลอยู่ประกอบไปด้วย ภาษาไทย ภาษาอังกฤษ เป็นหลัก และอาจจะมีภาษาอื่นๆปนอยู่ด้วย Lexer ที่น่าจะใช้ได้คือ AUTO_LEXER, MULTI_LEXER, WORLD_LEXER หลังจากได้ทดสอบกำหนดค่า Lexer ให้กับฐานข้อมูล และทดสอบค้นหาด้วย เลขไทย พบว่าจะต้องใช้ WORLD_LEXER จึงจะสามารถรองรับกรณีนี้ได้ โดยใช้คำสั่งดังนี้ EXEC CTX_DDL.CREATE_PREFERENCE(‘WorldLex’, ‘world_lexer’); DROP INDEX USER01.IDXFT_THAI_LIBRARY_BOOKNAME; CREATE INDEX USER01.IDXFT_THAI_LIBRARY_BOOKNAME ON USER01.THAI_LIBRARY(BOOK_NAME)INDEXTYPE IS CTXSYS.CONTEXTPARAMETERS(‘LEXER WorldLex STOPLIST CTXSYS.EMPTY_STOPLIST SYNC(ON COMMIT)’)NOPARALLEL; USER01 คือ User ของฐานข้อมูล Oracle THAI_LIBRARY คือ ชื่อตาราง BOOK_NAME คือ ชื่อคอลัมภ์ ที่ต้องการทำ Index IDXFT_THAI_LIBRARY_BOOKNAME ชื่อ ตาราง index ผลพลอยได้ จากการปรับในครั้งนี้พบว่าเดิมต้องทำการตัดคำให้เรียบร้อย (เนื่องจากค่า Default คือ Basic Lexer ที่แบ่งคำด้วยช่องว่างเท่านั้น) เพื่อค้นหา แต่เมื่อปรับ Lexer ให้ถูกต้องสามารถส่งคำค้นเป็นประโยคยาวๆ ไปค้นหาได้เลย หวังว่าบทความนี้จะเป็นประโยชน์กับท่านที่ใช้งาน Full Text Search ของ Oracle และประสบปัญหาคล้ายๆกันนี้ครับ

Read More »

Migrate จากฐานข้อมูล MySql มายัง Oracle ด้วย Sql Developer

เนื่องจากงานที่รับผิดชอบ จะต้องมีการโอนย้ายข้อมูลจากฐานข้อมูลอื่นๆมายัง Oracle เป็นประจำ พบว่าการย้าย MySql มายัง Oracle นั้นสามารถทำได้ง่ายมาก (อาจเพราะเจ้าของเดียวกัน) โดยมีวิธีดังนี้ 1. ดาวส์โหลดและติดตั้ง Oracle SQL Developer 2. ทำการเชื่อมต่อไปยังฐานข้อมูล Oracle ด้วย User system 3. สร้าง Oracle User สำหรับเก็บข้อมูลจาก MySql และกำหนดสิทธิให้เรียบร้อย 4. ดาวส์โหลดไฟล์ Third Party JDBC Driver สำหรับ My Sql 5. เปิดการใช้งาน Third Party JDBC Driver โดยไปที่ Tools > Preferences > Database > Third Party JDBC Drivers 6. ทำการ Restart โปรแกรม Sql Developer เมื่อทำการ New Connection จะมีตัวเลือกเพื่อเชื่อมต่อไปยัง My Sql 7. ทำการเชื่อมต่อไปยัง My Sql  หากต้องการเพียง Data, Schema สามารถคลิกขวาตารางที่ต้องการเลือก Copy To Oracle ได้เลย เพียงเท่านี้ ข้อมูล Table, Field ก็จะถูกโอนย้ายและ Map Data Type ให้อัตโนมัติสามารถ Query จาก Oracle ได้เลย แต่สำหรับงานที่ต้องการ Constraint, Trigger, ฯลฯ ด้วย จะมีขั้นตอนเพิ่มเติมดังนี้ ไปที่  Tools > Migration > Migrate กำหนด User ที่จะใช้เป็น Migrate Repository (เก็บข้อมูลต่างๆขณะดำเนินการ Migrate) 2. กำหนดโฟลเดอร์จัดเก็บ Script, Log file 3. เลือก Connection My Sql ที่ต้องการ Migrate 4. เลือก My Sql User ที่ต้องการ Migrate 5. การ Map Data Type สามารถใช้ค่า Default ได้ 6. เลือก Sql Object ที่ต้องการ 7. เลือก Connection ของ DB User ที่ใช้เก็บโครงสร้าง และคำสั่งต่างๆ ที่ระบบใช้ในการ Migrate 8. กำหนด User เป้าหมายที่จะนำข้อมูลเข้า จากนั้นเลือก Finish เพียงเท่านี้ก็เรียบร้อยครับ ข้อควรระวังคือการเลือก Repository User ควรสร้างขึ้นมาใหม่ เนื่องจากจะมีการสร้าง Table ขึ้นมาระหว่างการ Migrate และการกำหนดสิทธิให้กับ User ต่างๆให้ครบถ้วน แบบที่สองดูเหมือนหลายขั้นตอน แต่ก็เป็นแบบ Wizard ที่ใช้งานได้ไม่ยาก หวังว่าบทความนี้จะเป็นประโยชน์ครับ

Read More »

Grid Infrastructure 18c ตอน 5 (ตอนจบภาคติดตั้ง)

ตอนนี้จะมาติดตั้ง oracle database 18c เข้าระบบด้วยผู้ใช้ oracle เปิด terminal พิมพ์คำสั่ง (จากครั้งที่แล้วยังเหลือ disk อีก 2 ลูก) ต่อด้วยคำสั่ง SQL ต่อไปนี้ ได้ดังรูป เริ่มติดตั้ง database ได้ดังรูป Set Up Software Only กด Next ได้ดังรูป เลือก Oracle Real Application Clusters database installation ได้ดังรูป กด Next ได้ดังรูป เลือก Standard Edition 2 กด Next กด Next กด Next รอแป๊บ กด Install รอจนมีหน้าต่างใหม่ว่า เปิด Terminal แล้วพิมพ์คำสั่งต่อไปนี้ ที่ rac1 และ rac2 กลับไปที่หน้าต่าง Execute Configuration Scripts กด OK กด Close ต่อไปสร้าง database ด้วยคำสั่ง จะได้ เลือก Create a database กด Next กด Next เลือกดังรูปกด Next กด Next ตั้ง Global database name และ SID Prefix เอาเครื่องหมายถูกหน้า Create Container database ออก กด Next คลิก Browse… เลือก DATA กด OK กด Next คลิกเลือก Specify Fast Recovery Area Browse ไฟล์เลือก +MGMT ช่อง Fast Recovery Area size: เป็นขนาด HDD–10% กด Next ปรับแต่ง memory ตามความเหมาะสม คลิกช่อง Sizing ปรับจำนวนโปรเซส กดช่อง Character sets เลือกตามรูป กด Next กด Next ตั้ง Password กด Next กด Next รอแป๊บ กด Finish รอระหว่างนี้ไปพักได้ กด Close เสร็จ สิ่งที่ต้องหาข้อมูลเพิ่มเติม disk group ต่างๆ ไว้ทำอะไร และอาจปรับลดให้เหลือเฉพาะ disk group เดียว จะได้มีเนื้อที่มากขึ้นกว่าตอนนี้ ที่มีแค่ 1TB automatic start/stop server ตอนนี้ทำเสร็จไม่สามารถ restart ได้เพราะทำไม่เป็น ทำแค่ how to ติดตั้งเพียงอย่างเดียวจึงได้เพียงเท่านี้ จบขอให้สนุก

Read More »

Grid Infrastructure 18c ตอน 4

โหมดแทบ จะ next technology เข้าระบบด้วยผู้ใช้ oracle เปิด terminal พิมพ์คำสั่งต่อไปนี้ จะได้ดังรูป เลือก Configure Oracle Grid Infrastructure for New Cluster กด Next จะได้ดังรูป เลือก Configure an Oracle Standalone Cluster กด Next จะได้ดังรูป เลือก Create Local SCAN แก้ชื่อให้ตรงกับที่ขอจดกับ DNS (rac-scan) ดังรูป กด Next จะได้ดังรูป ให้กด Add… เพื่อเพิ่ม rac2 ดังรูป กด Next จะได้ดังรูป ให้เปลี่ยนเป็นตามรูป (ซึ่งตัวอย่างนี้ใช้ iSCSI) กด Next จะได้ดังรูป เลือก Configure ASM using block devices กด Next จะได้ เลือก Yes กด Next ได้ดังรูป เปลี่ยน Disk Discovery Path เป็น /dev/oracleasm/disks/* โดยการคลิก Change Discovery Path… คลิก Specify Failure Groups… กรอกและเลือกดังรูป กด OK ในส่วนของ Redundancy เลือก Normal ในช่อง Select Disks เลือก Disk 3 ลูก ระบุ Failure Group ต่างกัน Group ตามที่สร้างไว้ กด Next จะได้ดังรูป เลือก External และ disk 1 ลูก กด Next จะได้ เลือก Use same passwords for these accounts แล้ว ตั้ง password กด Next ได้ดังรูป เลือก Do not use Intelligent Platform Management Interface (IPMI) กด Next ได้ดังรูป กด Next แล้วเลือกดังรูป dba, oper, asmoper จะได้ดังรูป กด Next ได้ดังรูป เลือก Yes ได้ดังรูป กด Next ได้ดังรูป กด next ได้ดังรูป กด Install ได้ดังรูป รอจนกระทั่ง ให้รันคำสั่งต่อไปนี้ ใน terminal เริ่มจาก rac1 แล้วต่อด้วย rac2 กด enter 1 ครั้งแล้วรอ ให้สคริปต์ทำงานไปจนกว่าจะเสร็จ โดยสังเกตด้วยต้องไม่มีคำว่า Fail เลย เมื่อครบทั้ง 2 คำสั่งที่ rac1 แล้ว ให้ทำซ้ำที่ rac2 อาจสั่งไปจาก rac1 ก็ได้ เมื่อสั่งคำสั่งครบทั้ง 2 เครื่องแล้วให้กลับมา rac1 แล้วกด OK ได้รูป พักดื่มน้ำปัสสาวะได้ เนื่องจากค่อนข้างนาน กลับมากด Close ได้เลย

Read More »