โมเดล 4B เทรนเองด้วยงบ $1,200 ทำ query plan เร็วกว่า Postgres 1.81 เท่า — แต่ต้องอ่านเงื่อนไขให้ครบ
16 ก.ย. 2026 Rohan Bansal เผยแพร่รายงานการทดลองชื่อ qorl ที่ตั้งคำถามตรงไปตรงมาว่า โมเดลภาษาเปิดขนาดเล็กจะเรียนรู้การปรับ query plan ของ Postgres ให้ดีกว่า planner ของตัว Postgres เองได้หรือไม่ คำตอบที่เขาได้คือ ได้ โมเดลขนาด 4B ที่ตอนแรกทำงานนี้ไม่เป็นเลย หลังผ่าน supervised fine-tuning และ reinforcement learning ทำ geometric mean speedup 1.81 เท่า และลดเวลารวมของ workload ลง 44.7% บน Join Order Benchmark ด้วยต้นทุนทั้งโครงการ $1,200
งานนี้น่าสนใจกับนักพัฒนาไม่ใช่เพราะตัวเลข แต่เพราะรูปแบบของมัน นี่คือกรณีตัวอย่างที่ชัดที่สุดอันหนึ่งของสิ่งที่หลายบริษัทกำลังคิดอยู่ว่า เอาโมเดลเปิดตัวเล็ก มาเทรนบนงานเฉพาะทางที่ ตรวจผลได้ด้วยตัวเลขเดียว โดยไม่ต้องใช้คลัสเตอร์ GPU และไม่ต้องสร้างโมเดลใหม่ทั้งตัว ข้อสำคัญคือรายงานนี้ยังเปิดตัวเลขที่ไม่สวยไว้ครบด้วย ซึ่งเป็นส่วนที่มีค่าที่สุด
ทำไมต้องเป็นปัญหานี้
Bansal อ้างงานคลาสสิก How Good Are Query Optimizers, Really? ของ Leis และคณะ (VLDB 2015) ที่ถามคำถามเดิมซ้ำอีกครั้งในปี 2025 แล้วพบว่า query optimizer ยังห่างจากดีพอ เหตุผลคือ join ordering เป็นปัญหา NP-hard และ Postgres ต้องเดา cardinality จากสถิติแทนที่จะนับจริง
เขาเลือกกรอบปัญหาอย่างระมัดระวัง ไม่ได้พยายามสร้าง cardinality estimator ที่ดีกว่า (สู้กับงานวิจัยสะสมหลายสิบปี และ latency ของการ inference จะกินกำไรหมด) แต่เล็งไปที่ analytic workload ที่ query เดิมถูกรันซ้ำเป็นพัน ๆ ครั้ง ถ้ายอมจ่ายค่ารัน query นั้นเพิ่มหลักสิบถึงหลักร้อยครั้งตอนเทรน ต้นทุนเฉลี่ยต่อการรันจริงจะต่ำลงมาก เป้าหมายไม่ใช่ชนะ Postgres บน query ที่รันครั้งเดียว
โมเดลไม่ได้เขียน plan เอง แต่ออก hints ผ่าน pg_hint_plan (เช่น Leading, HashJoin, NestLoop, IndexScan, Parallel) แล้วมี harness ชื่อ qo-agent ที่ให้เครื่องมือ 6 ตัว ตั้งแต่ inspect_relation, get_column_stats, get_plan ไปจนถึง evaluate_candidate เป็นสภาพแวดล้อมแบบ agentic หลายเทิร์น
ฐานที่ใช้คือ empero-ai/Qwen3.8-4B-Distill (Apache-2.0) จากแล็บเล็กในเยอรมนีชื่อ Empero ที่เอา Qwen 3.8 ขนาด 2.4T เป็น teacher กลั่นลง Qwen 3.5 4B เพราะตระกูล Qwen 3.8 ไม่มีรุ่น 4B ออกมา ฮาร์ดแวร์เริ่มจากเครื่องที่บ้านชื่อ FLOPper (RTX 3090 สองใบ ใบละ 24 GB)
จุดตั้งต้นแย่กว่าที่คิด
ก่อนเทรน เขาวัด baseline ไว้สองด้าน ด้านบน เขาเช็คก่อนว่าโมเดลระดับ frontier ทำงานนี้ได้จริงไหม บนตัวอย่าง JOB 10 query:
| โมเดล | จำนวน candidate | S_geo | S_workload | Regressions |
|---|---|---|---|---|
| GPT-6 Astra (medium) | 1 | 0.85x | 1.00x | 3 |
| GPT-6 Astra (medium) | 5 | 2.54x | 2.12x | 0 |
| Astra (medium + reasoning summaries) | 5 | 2.39x | 1.57x | 1 |
| Qwen 3.8 2.4T (medium) | 1 | 2.02x | 1.30x | 1 |
| Qwen 3.8 2.4T (medium) | 5 | 2.26x | 1.35x | 1 |
ช่องว่างระหว่าง 1 candidate กับ 5 candidate บอกว่า agent เรียนรู้จาก feedback ระหว่างรันได้จริง เขาจึงเลือกทำเป็น agent หลายเทิร์นแทนการ one-shot
ด้านล่าง โมเดล 4B ดิบทำได้ แย่มาก จาก 113 query มี 81 query ที่ไม่ได้ candidate ที่ใช้ได้เลย อีก 16 query เลือกไม่สำเร็จ สุดท้ายเหลือ plan ที่ทั้งถูกโครงสร้าง ถูกต้องตาม schema และต่างจาก Postgres จริง ๆ แค่ 6 จาก 113 query ปัญหาส่วนใหญ่ไม่ใช่เรื่องฐานข้อมูล แต่เป็นเรื่องที่โมเดลไม่เข้าใจ harness ที่ห่อมันอยู่ เช่น ออก object ผิดรูป เรียกเครื่องมือผิดจังหวะ หรือสร้าง Leading tree ที่มี subtree ไม่เชื่อมกันใน join graph
สองขั้น: สอนภาษาก่อน แล้วค่อยสอนงาน
ขั้นแรกคือ off-policy distillation ผ่าน SFT เพื่อให้ 4B พูด “ภาษาของ harness” ได้ก่อน โดยใช้ trajectory จาก GPT-6 Astra เขาเลือก Astra เป็น teacher แทน Qwen 3.8 2.4T เพราะเทียบกันแล้ว Astra ใช้ 7.6 เทิร์นและ context เฉลี่ย 22,009 tokens ขณะที่ Qwen ใช้ 12.2 เทิร์นและ 45,144 tokens และรัน 10 query จบใน 3 นาที 13 วินาที เทียบกับ 15 นาที 51 วินาที ข้อเสียคือ API ของ Astra ไม่ส่ง reasoning tokens จริง ให้แต่สรุป ซึ่งมีงานวิจัย (How to Steal Reasoning Without Reasoning Traces) ชี้ว่าเทรนจากสรุปทำให้ student แย่ลง
การเทรนใช้ LoRA ล้วน น้ำหนักเต็ม 4.66 พันล้านพารามิเตอร์คือ 9.32 GB ที่ bf16 แต่ adapter ที่เทรนจริงมีแค่ 21.2 ล้านพารามิเตอร์ ขนาด 42.5 MB
ขั้นที่สองคือ agentic RL ด้วย GRPO เวอร์ชันดัดแปลง reward คือ log ธรรมชาติของ speedup หักด้วย 0.1 ต่อ candidate ที่ไม่ถูกต้อง หักอีก 0.05 ต่อ plan ที่ fingerprint ซ้ำกับ default หรือกับ candidate ก่อนหน้า และหักรวด -3 ถ้าทั้ง trajectory ไม่มี candidate ที่ใช้ได้เลย ผลคือบทเรียนที่ตรงไปตรงมา: โทษ -3 ที่หนักเกินไปทำให้โมเดล กลัวจนเล่นปลอดภัย ส่งแผน default ของ Postgres กลับมาซ้ำ ๆ ยอมโดนหัก 0.05 แทน และ GRPO แบบพื้นฐานยิ่งขยายปัญหานี้ เขาจึงต้องออกแบบการคำนวณ advantage ใหม่
รอบ RL แรกก็ล้มเช่นกัน — 120 optimizer updates ที่ learning rate 1e-06 ได้ 1.14x geo / 0.99x workload แย่กว่าจุดตั้งต้น SFT ที่ 1.16x / 1.06x ต้องขยับ learning rate ขึ้นหนึ่ง order เป็น 1e-05 เพิ่ม batch เป็น 16 และ rollouts ต่อ query จาก 4 เป็น 8 ก่อนจะไปถึง checkpoint สุดท้ายที่ 1,200 updates
ตัวเลขที่ต้องอ่านให้ครบ
นี่คือส่วนที่พาดหัวมักตกหล่น ผลสุดท้ายมีสามแถว ไม่ใช่แถวเดียว:
| วิธีเลือกคำตอบ | S_geo | S_workload | Wins | Regressions |
|---|---|---|---|---|
| โมเดลเลือกเอง (339 trajectories) | 1.40x | 1.24x | 119 | 7 |
| เลือก feedback ที่ดีที่สุดใน trajectory เดียว | 1.44x | 1.29x | 129 | 1 |
| เลือกที่ดีที่สุดจาก 3 trajectories (สูงสุด 15 candidates) | 1.81x | 1.81x | 68 | 0 |
ตัวเลข 1.81 เท่าที่เป็นพาดหัวคือแถวล่างสุด ซึ่งหมายถึง รัน agent 3 รอบต่อ query แล้วเลือกผลที่ดีที่สุด ถ้าปล่อยให้โมเดลตัดสินใจเองแบบที่จะเกิดในการใช้งานจริงแบบอัตโนมัติ ตัวเลขคือ 1.40 เท่า และมี 7 query ที่ช้าลง ในกรอบปัญหาของเขา (query ที่รันซ้ำเป็นพันครั้ง) การรันหลายรอบแล้วเก็บผลดีที่สุดถือว่าสมเหตุสมผล เพราะทำครั้งเดียวแล้วใช้ยาว แต่มันไม่ใช่ตัวเลขเดียวกับ “โมเดลนี้เก่งกว่า Postgres”
ที่น่าชมคือ เขาเปิดเรื่อง noise ในการวัดเอง งานนี้วัดเวลาจริงบนเครื่อง ไม่ใช่ประมาณจาก cost model เขาพบว่า job-13b มีเวลารันแยกเป็นสองกลุ่ม และถ้าใช้ median จาก 3 ครั้ง จะมีโอกาส ราว 20% ที่ median ของฝั่งใดฝั่งหนึ่งไปตกในกลุ่มช้า ทำให้เกิด “phantom speedup” ปลอม 14–26% ที่ถูกป้อนกลับเข้าไปเป็นสัญญาณให้โมเดลเรียน เขาจึงต้องรันสลับคู่ (candidate, default) สามคู่ต่อเนื่องกัน เทียบ median กับ median และประกาศเป็นเสมอถ้าต่างกันไม่ถึง 5% รวมทั้งย้าย Postgres ออกจากโหนด Lambda ที่เช่ามาไว้ที่เครื่องตัวเอง เพราะสงสัยว่าใช้ CPU ร่วมกับผู้เช่ารายอื่น
สิ่งที่โมเดลเรียนรู้จริงก็ถูกวิเคราะห์จาก trace: จาก 1,347 actions โมเดลออก scan hints 1,141 ครั้ง, Leading tree 917 ครั้ง, Parallel 572 ครั้ง แต่ใช้การแก้ค่า Rows แค่ 146 ครั้ง และ 295 จาก 337 การค้นหาเริ่มด้วยการไปดูตาราง สถิติคอลัมน์ หรือ plan เดิมก่อนเสมอ
ข้อจำกัดที่ควรรู้ก่อนเอาไปอ้าง
- เทรนและทดสอบบนฐานข้อมูลเดียวกัน เทรนบน CEB ทดสอบบน JOB ซึ่งใช้ชุดข้อมูล IMDb ทั้งคู่ ผู้เขียนบอกว่านี่คือความตั้งใจ เพราะต้องการให้โมเดลรู้จักฐานข้อมูลนั้นดี ไม่ได้ต้องการให้ generalize ข้ามฐานข้อมูล เขาเช็คแล้วว่า topology ของ join graph ระหว่าง CEB กับ JOB ไม่ทับกัน จึงไม่ต้องตัด query ออก แต่แปลว่า ไม่มีหลักฐานว่าย้ายไปฐานข้อมูลอื่นแล้วยังได้ผล
- ยังตามหลังโมเดล frontier Astra ที่ 5 candidate ทำ 2.54x บนตัวอย่าง 10 query ขณะที่ 4B ที่เทรนแล้วทำ 1.81x บน 113 query — คนละชุดวัด เทียบกันตรง ๆ ไม่ได้ แต่ทิศทางชัดว่า 4B ยังไม่ชนะ frontier
- ผลขึ้นกับการจูน Postgres และ cache ผู้เขียนระบุเองว่าการ calibrate Postgres อ่อนไหวกับการตั้งค่า cache ของฮาร์ดแวร์มาก
- โค้ดเปิด แต่ยังไม่มี LICENSE รีโป polyphilz/qorl เปิดอ่านได้ ตอนตรวจสอบเมื่อ 17 ก.ย. ยังไม่มีไฟล์ LICENSE ในรีโป ซึ่งตามค่าเริ่มต้นหมายถึงสงวนลิขสิทธิ์ ใครจะเอาไปใช้ต่อในงานบริษัทควรรอหรือถามเจ้าของก่อน และ ยังไม่มีการปล่อย LoRA adapter ที่เทรนแล้ว
มุมมอง AI Curator
สิ่งที่ผมคิดว่าสำคัญที่สุดของงานนี้ไม่ใช่ 1.81 เท่า แต่เป็น $1,200 กับ adapter ขนาด 42.5 MB ตัวเลขนี้อยู่ในระดับที่ทีมวิศวกรรมในไทยจ่ายได้จากงบทดลองปกติ ไม่ต้องขออนุมัติโครงการ ถ้าคุณมี data warehouse ที่รัน query ชุดเดิมซ้ำทุกวัน คุณมีทั้งสองอย่างที่งานนี้ต้องการอยู่แล้ว คือ ข้อมูลของตัวเอง และฟังก์ชันวัดผลที่ไม่ต้องมีคนมาให้คะแนน — เวลาที่ query ใช้รัน
และนี่คือแก่นจริง ๆ ของบทเรียน งานที่ RL ทำได้ดีคืองานที่ “ถูกหรือผิด” ตรวจได้เองด้วยเครื่อง ไม่ใช่งานที่ต้องมี human preference หรือ LLM-as-judge มาตัดสิน องค์กรไทยจำนวนมากมีงานแบบนี้เต็มไปหมดโดยไม่รู้ตัว ตั้งแต่การจัดตารางเดินรถ การจัดเส้นทางส่งของ ไปจนถึงการตั้งค่า config ของระบบที่วัด throughput ได้ โจทย์ไม่ใช่ “จะเอา LLM มาทำอะไรดี” แต่เป็น “งานไหนในบ้านเราที่วัดผลได้เป็นตัวเลขเดียว และถูกทำซ้ำบ่อยพอจะคุ้มค่าเทรน”
แต่ผมอยากให้สังเกตส่วนที่เป็นบทเรียนราคาแพงกว่าด้วย เวลาส่วนใหญ่ของโครงการนี้ไม่ได้หมดไปกับการเทรน แต่หมดไปกับการทำให้การวัดผลเชื่อถือได้ เรื่อง phantom speedup 20% คือตัวอย่างที่ควรถูกอ่านซ้ำ ถ้าเขาไม่จับเรื่องนี้ โมเดลจะถูกสอนด้วยสัญญาณขยะหนึ่งในห้าครั้งโดยที่ทุกอย่างดูปกติดี และมันไปคู่กันพอดีกับบทความของ Microsoft ที่ออกวันเดียวกันเรื่อง sandbox ของ agent eval ที่รั่ว — คนละปัญหา แต่รากเดียวกัน คือ การวัดผลที่ดูผ่านแต่วัดผิดสิ่ง ทีมที่เพิ่งเริ่มทำ RL environment เองมักทุ่มเวลาให้ reward function แล้วปล่อยเรื่องการวัดให้เป็นหน้าที่ของโชค
ข้อสุดท้าย ผมอยากให้เครดิตกับวิธีที่รายงานนี้เขียน มันเปิดทั้งรอบที่ล้ม (RL 120 updates ที่แย่กว่า SFT) เปิดทั้งตัวเลขที่โมเดลเลือกเองซึ่งต่ำกว่าพาดหัวมาก และเปิดว่า teacher เป็นโมเดลปิด ในยุคที่บล็อกเทคนิคส่วนใหญ่โชว์แต่กราฟที่ชนะ นี่คือมาตรฐานที่เราควรเรียกร้องจากทั้ง independent researcher และจากแล็บใหญ่ — และเป็นเหตุผลที่งานของคนคนเดียวบนสองการ์ด RTX 3090 น่าเชื่อถือกว่าตารางเทียบ benchmark ของผู้ขายจำนวนไม่น้อย
แหล่งข่าว
- Rohan Bansal — Training a 4B model to produce 81% faster query plans than Postgres (16 ก.ย. 2026)
- GitHub — polyphilz/qorl (โค้ดทั้งหมดของโครงการ)
- Hugging Face — empero-ai/Qwen3.8-4B-Distill (โมเดลฐาน Apache-2.0)
- Leis et al. — How Good Are Query Optimizers, Really? (VLDB 2015, ที่มาของ Join Order Benchmark)
อ่านเพิ่มในหมวด งานวิจัย
Anthropic ให้ Claude สร้างชุดข้อมูลที่ดูไร้พิษภัยแต่ทำโมเดลเบี้ยว ซ่อนในเรื่องเลี้ยงผึ้งและมวยปล้ำ จนผ่านระบบตรวจที่คล้ายของจริง
ทีม Alignment ของ Anthropic ให้ Claude ปีนหาชุดข้อมูล fine-tune ที่หลบ monitor ได้ ผลคือซ่อนพฤติกรรมในงานเขียนแนวบทบาทสมมติ และโมเดลที่เทรนแล้วนำไปใช้ในบุคลิกตัวเอง ผลซ้ำได้บน Qwen 3.6 27B แต่การทดลองเอื้อฝ่ายโจมตีมากและไม่ได้สะท้อนโมเดลที่ใช้งานจริง
Memdoor ทำซ้ำ GVS5H ได้: ทีม Qwen3.8-27B ห้าตัวตามทัน Fable 5 บนโจทย์ LiveCodeBench Hard แต่ผู้ทำบอกเองว่า 'เท่า' ไม่ใช่ 'ชนะ'
Memdoor ปล่อย workflow team-solve ที่เขียนวิธี GVS5H เป็น YAML ล้วนและทำคะแนน 9.8/10 บน LiveCodeBench Hard 10 ข้อ เทียบกับ 8.0 ของ Fable 5 แบบเรียกครั้งเดียว แต่ตัวอย่างเล็กและมีข้อจำกัด ส่วนงานวิจัยต้นฉบับชี้ว่าวิธีนี้ไม่ได้ช่วยทุกโมเดล
QwenPU รัน LLM ซ้อนใน LLM ด้วยหน่วยเวกเตอร์ที่คอมไพล์ลงในน้ำหนัก Qwen3.5-4B ส่วน bootgpt ทำให้เครื่อง 386 บูตเข้าโมเดลภาษาโดยไม่มี OS
ผู้สร้าง Qwenputer ปล่อย QwenPU เมื่อ 31 ต.ค. รัน stories260K ของ Karpathy บนหน่วยเวกเตอร์ที่คอมไพล์ลงในน้ำหนัก Qwen3.5-4B ลดเหลือ 53,000 trace token ต่อหนึ่ง token เรื่องเล่า วันเดียวกัน bootgpt ใส่โมเดล int8 ขนาด 11.5KB ให้บูตบนเครื่อง 386 โดยไม่มี OS