ในโลกของการพัฒนาซอฟต์แวร์ที่ทันสมัย ผู้ใช้งานคาดหวังประสบการณ์ที่ตอบสนองได้รวดเร็วและราบรื่นอย่างยิ่งยวด ไม่ว่าระบบเบื้องหลังกำลังประมวลผลงานที่ซับซ้อนและกินทรัพยากรสูงแค่ไหนก็ตาม ปัญหาที่นักพัฒนาต้องเผชิญคือ UI Freezing หรืออาการที่โปรแกรมหยุดนิ่งเมื่อต้องรอการประมวลผลที่ยาวนาน
หัวใจสำคัญของการแก้ไขปัญหานี้คือการทำความเข้าใจแนวคิดเรื่อง Concurrency (ภาวะพร้อมกัน) และ Parallelism (การทำงานขนาน) การทำความเข้าใจแนวคิดเหล่านี้ช่วยให้เราสามารถแยกภาระงานที่ใช้เวลานานออกจาก Main Thread หรือ Connection Thread หลัก เพื่อให้การตอบสนองของระบบยังคงลื่นไหลอยู่เสมอ
💡 หลักการ Concurrency ในบริบทของฐานข้อมูล
แม้ว่า Qt จะเป็น Framework สำหรับ GUI แต่หลักการจัดการงานเบื้องหลัง (Background Processing) นั้นเป็นหลักการสากลที่นำมาปรับใช้ได้กับทุกระบบ รวมถึง PostgreSQL ด้วย เมื่อเราพูดถึง Concurrency ใน PostgreSQL เราไม่ได้หมายถึงการรันโค้ดหลายเธรดในระดับแอปพลิเคชันโดยตรง แต่หมายถึงการออกแบบระบบที่สามารถรับและประมวลผลคำขอ (Requests) จำนวนมากได้อย่างมีประสิทธิภาพ โดยไม่ทำให้ Connection หลักเกิดการติดขัด (Blocking) ซึ่งเป็นหลักการเดียวกับการย้ายงานหนักออกจาก GUI Thread
⚙️ การจำลองการทำงานแบบ Background Worker ใน PostgreSQL
ในเชิงของ PostgreSQL เราสามารถจำลองการทำงานแบบ Asynchronous หรือ Background Worker ได้โดยการใช้ตารางคิว (Job Queue) และฟังก์ชัน (Stored Procedure) เพื่อให้ Processors อื่นๆ เข้ามาดึงงานไปประมวลผลทีหลัง แทนที่จะให้ Connection หลักรอนานจนหมดเวลา (Timeout)
SQL
-- 1. สร้างตารางคิวสำหรับเก็บงานที่ต้องประมวลผลเบื้องหลัง (Job Queue) ---------------------------------------------------------------------------------
CREATE TABLE background_jobs (
job_id SERIAL PRIMARY KEY,
data TEXT NOT NULL, -- ข้อมูลที่ต้องใช้ในการประมวลผล เช่น 'apple,banana,orange'
status VARCHAR(20) DEFAULT 'PENDING',
created_at TIMESTAMP DEFAULT NOW()
);
-- 2. สร้างฟังก์ชัน Worker ที่ทำหน้าที่ประมวลผลงาน (จำลองการทำงานที่ใช้เวลานาน) ---------------------------------------------------------------------------------
CREATE OR REPLACE FUNCTION process_job(p_job_id INT) RETURNS TEXT AS $$
BEGIN
-- จำลองการคำนวณที่กินเวลานาน (แทนการทำงานของ QThread)
PERFORM pg_sleep(0.5);
-- อัปเดตสถานะงานเมื่อเสร็จสิ้น
UPDATE background_jobs SET status = 'COMPLETED' WHERE job_id = p_job_id;
RETURN 'Job ' || p_job_id || ' processed successfully.';
END;
$$ LANGUAGE plpgsql;
-- 3. การส่งงานเข้าคิว (Enqueueing the job) ---------------------------------------------------------------------------------
INSERT INTO background_jobs (data) VALUES ('1,2,3');
-- 4. การเรียกใช้ Worker (จำลองการเรียกใช้ QThreadPool)
SELECT process_job(1);
✅ สรุปแนวคิดในการออกแบบระบบ
การออกแบบระบบที่คำนึงถึง Concurrency ไม่ได้หมายถึงการใช้เธรดจำนวนมาก แต่หมายถึงการออกแบบที่ ไม่บล็อก (Non-blocking) การทำงานหลักควรเป็นเพียงการบันทึกงานเข้าคิว (Insert into `background_jobs`) และปล่อยให้ Processors หรือ Worker อื่นๆ เข้ามาจัดการงานเหล่านั้นในภายหลัง ด้วยการใช้รูปแบบ Job Queue นี้ ทำให้ระบบหลักสามารถตอบสนองต่อผู้ใช้ได้ทันที แม้ว่างานเบื้องหลังจะใช้เวลาประมวลผลนานเพียงใดก็ตาม