Query ข้อมูลในตัวแปร JavaScript ผ่านภาษา SQL ด้วย alasql.js กันเถอะ

Earthchie Thanarat
Earthchie
Published in
2 min readOct 5, 2017

เป็นอีกบล็อคที่เกิดจาก status บนเฟซบุคครับ (เอาอีกแล้ว)

เรื่องมันเป็นงี้ครับ คือผมได้รับ requirement จากลูกค้าว่า ต้องการให้เว็บออกรายงานฉบับนึง เป็นรายงานเจาะลึก ซึ่งจะมีการนำเอาข้อมูลมาแสดงผลตามมิติต่างๆ แบ่งออกได้เป็นจังหวัดละ 440 มิติ ทั่วประเทศรวมกันก็มีตัวเลขมากกว่า 440*77 = 33,880 ตัวเลยล่ะครับ

ตัวเลข 1 ตัว ได้จากการ query ข้อมูล 1 ครั้ง นั่นหมายความว่า การที่จะออก report ฉบับนี้ฉบับเดียว ต้อง query มากถึง 33,880 ครั้งกันเลยทีเดียว

ลำพังเรื่องจำนวน query ก็หนักใจมากพอแล้ว แต่ด้วย requirement เสริมอีกข้อ นั่นก็คือ ต้องการให้ realtime ถึงแม้ว่าเราจะโน้มน้าวให้ลูกค้าเข้าใจแล้วว่า realtime ไม่มีอยู่จริง แต่ลูกค้าก็ยอมรับให้ข้อมูลมันดีเลย์ได้เพียงแค่ 5 นาทีเท่านั้น

…แปลว่าแคชได้แค่ 5 นาที แทบไม่มีประโยชน์เลย

เคราะห์ซ้ำกรรมซัด ด้วยปัญหาที่เรียกว่า technical debt ที่โปรเจคนี้สั่งสมเอาไว้จากกรอบเวลาที่น้อยนิด เราจึงไม่มี api เฉพาะงาน เรามีเพียงแต่ api อเนกประสงค์ ถ้าให้เข้าใจง่ายๆ ก็นึกถึง BaaS ของ Parse เข้าไว้ครับ เป็นแบบนั้นเลย

แปลว่า 1 query = 1 request

ครับ เข้าเว็บหน้านี้หน้าเดียว เกิด request ขึ้นทั้งหมด 33,880 requests

บ้าไปแล้ว!

ด้วยปริมาณ request ที่มากขนาดนี้ มันจึงกิน RAM มหาศาลตามไปด้วย คอมดีๆ ส่วนมากมี RAM 8GB ใช่ไหมครับ …ผมอยากบอกว่า ไม่พอครับ ทำงานได้แค่ราวๆ 25,000 requests แรกเท่านั้น ที่เหลือขึ้น error insufficient resource

ยืมภาพคนอื่นมาจาก https://moodle.org/mod/forum/discuss.php?d=320917

นี่ยังไม่พูดถึงปริมาณทราฟฟิคที่เกิดขึ้นนะครับ มันคือการ flood server ตัวเองดีๆ นี่เอง จะบ้ารึไง 1 session ก่อให้เกิด 33k concurrent ล่มกันหมดพอดี

alasql.js

https://github.com/agershun/alasql

พระเอกของเราครับ ก่อนจะไปต่อ ขอติดแท็กอีกที #JavaScriptจะครองโลก

ตอนนี้ ผมกลับมาตั้งหลักใหม่ เปลี่ยนวิธีคิดเลย ย้ายข้อมูลมา Query บนฝั่ง client ไปเลย จะได้แบ่งเบาภาระ server เพราะโหลดข้อมูลจาก server มาลงเครื่องนั้นใช้เวลาไม่นาน query นึง ได้มา 2,000 records (เป็นข้อจำกัดของ api) โดยข้อมูลมีราว 440,000 records ก็ใช้ประมาณ 220 request เท่านั้น ถึงจะยังเยอะ แต่ถ้าเทียบกับตัวเลขก่อนหน้าที่มี 3 หมื่นกว่า ทางนี้น่าคบหากว่าเยอะ

ทำเว็บใส่ loading animation สวยๆ พร้อมแจ้งความคืบหน้าระหว่างที่รอโหลดข้อมูล

เสร็จแล้วผมก็ทำเว็บใส่ loading animation สวยๆ พร้อมแจ้งความคืบหน้าระหว่างที่รอโหลดข้อมูล ใช้เวลาโหลดข้อมูลประมาณ 1 นาที ฝั่ง client ก็มี DB ทั้งก้อน ไว้ query ตามใจชอบแล้ว โชคดี ลูกค้าไม่มีปัญหาเรื่องเวลาที่ต้องรอ (ถ้าไม่นานหลายสิบนาทีอ่านะ)

จากนั้นเราก็เอา alasql.js ไป query ข้อมูลได้ทันที ด้วยภาษา SQL มีเปลี่ยนแปลงเล็กน้อยตรงชื่อ table เราเปลี่ยนไปใช้ ? แทน ดูโค้ดเลยดีกว่า เข้าใจง่ายกว่าเยอะ

alasql('SELECT SUM(grand_total) AS grand_total FROM ?',[DB]);

สบายเลยครับพี่น้อง แบบนี้จะเอามิติไหนก็ไม่กลัวแล้ว

ตัวอย่างโค้ดที่ผมเขียน

แถมผลพลอยได้คือเราไม่ต้องปวดหัวกับ async อีกต่อไป เพราะถ้าเรา ajax เราจะต้องคอยบริหาร callback วุ่นวายมาก แต่ตอนนี้ไม่ต้องปวดหัวแบบนั้นอีก

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

ป.ล. ถ้าไม่ชอบ SQL สามารถ query แบบ MongoDB ได้เหมือนกันนะ ใช้ตัวนี้ https://github.com/protobi/query ผมว่าแบบ MongoDB ทำ dynamic query ง่ายกว่า ยังไงก็ลองเล่นดูได้ครับ

--

--