ข้อโต้แย้งต่อ PGVector
(alex-jacobs.com)- ส่วนขยาย Postgres pgvector รองรับการค้นหาความคล้ายคลึงของเวกเตอร์ แต่มี ช่องว่างขนาดใหญ่ระหว่างระดับเดโมกับสภาพแวดล้อมการใช้งานจริง
- ดัชนี IVFFlat และ HNSW ต่างก็มีข้อดีข้อเสียชัดเจน โดยเฉพาะ HNSW มีปัญหาเรื่อง การใช้หน่วยความจำระดับหลาย GB ระหว่างสร้างดัชนี และใช้เวลาสร้างนาน
- การค้นหาแบบเรียลไทม์และการอัปเดตดัชนี ทำได้ยากในเชิงโครงสร้าง และเมื่อมี การแทรกและอัปเดตอย่างต่อเนื่อง จะเกิด การแย่งล็อกและประสิทธิภาพลดลง
- เนื่องจาก กลยุทธ์การกรอง (Pre/Post) และข้อจำกัดของ query planner จึงเกิด สมดุลที่ไม่เสถียรระหว่างความแม่นยำและความเร็วของการค้นหา
- ต้องลงมือสร้างความสามารถที่ ฐานข้อมูลเวกเตอร์เฉพาะทาง (Pinecone, Weaviate ฯลฯ) มีให้อยู่แล้วด้วยตนเอง และสุดท้ายจะนำไปสู่ ความซับซ้อนในการปฏิบัติการและต้นทุนที่เพิ่มขึ้น
ภาพรวมข้อจำกัดของ pgvector
- pgvector เป็นส่วนขยายที่เพิ่ม ความสามารถในการค้นหาความคล้ายคลึงของเวกเตอร์ ให้กับ Postgres และแม้จะทำงานได้ดีในเดโมแบบง่าย ๆ แต่ เมื่อใช้งานจริงจะเจอปัญหาด้านการขยายระบบ
- บทความตามบล็อกจำนวนมากพูดถึงเพียงการติดตั้งและตัวอย่างคิวรีง่าย ๆ โดยแทบไม่กล่าวถึง ปัญหาด้านประสิทธิภาพ หน่วยความจำ และการจัดการดัชนีที่เกิดขึ้นระหว่างใช้งานจริง
ปัญหาในการเลือกดัชนี
- pgvector มีดัชนีให้เลือก 2 แบบ คือ IVFFlat และ HNSW
- IVFFlat: โครงสร้างแบบอิงคลัสเตอร์ สร้างดัชนีได้เร็ว แต่ การตั้งค่าจำนวนคลัสเตอร์ส่งผลอย่างมากต่อประสิทธิภาพและความแม่นยำ
- ไม่สามารถกระจายคลัสเตอร์ใหม่ได้ จึง จำเป็นต้องสร้างดัชนีใหม่เป็นระยะ
- HNSW: โครงสร้างกราฟหลายชั้น ให้ ความแม่นยำและประสิทธิภาพที่สม่ำเสมอ แต่ ใช้หน่วยความจำสูงมากและสร้างดัชนีได้ช้า
- IVFFlat: โครงสร้างแบบอิงคลัสเตอร์ สร้างดัชนีได้เร็ว แต่ การตั้งค่าจำนวนคลัสเตอร์ส่งผลอย่างมากต่อประสิทธิภาพและความแม่นยำ
- เมื่อสร้างดัชนีสำหรับเวกเตอร์ระดับหลายล้านรายการ อาจใช้ RAM มากกว่า 10GB ซึ่งเป็น ภัยคุกคามโดยตรงต่อเสถียรภาพของฐานข้อมูลที่ใช้งานจริง
ความยากของการค้นหาแบบเรียลไทม์
- หลังแทรกข้อมูลใหม่ ระบบควรค้นหาได้ทันที แต่ ด้วยโครงสร้างการอัปเดตดัชนี การสะท้อนผลแบบเรียลไทม์จึงทำได้ยาก
- IVFFlat: เวกเตอร์ใหม่จะถูกเพิ่มเข้าไปในคลัสเตอร์เดิม และเมื่อเวลาผ่านไปจะเกิด ความไม่สมดุลของคลัสเตอร์ → ต้องรีบิลด์เป็นระยะ
- HNSW: ระหว่างการแทรกจะมีการอัปเดตกราฟ ทำให้เกิด การแย่งล็อกและภาระหน่วยความจำ
- ระหว่างการสร้างดัชนีใหม่ การรักษาความสอดคล้องของข้อมูลและความต่อเนื่องของบริการทำได้ยาก
- ในสภาพแวดล้อมจริงจำเป็นต้องใช้กลยุทธ์อ้อมหลายแบบ เช่น staging table, ดัชนีคู่, การ build แบบออฟไลน์, eventual consistency
ข้อจำกัดของการกรองและ query planner
- เมื่อผสาน การกรองเมตาดาต้า เช่น
status,user_id,categoryเข้ากับการค้นหาเวกเตอร์ การเลือก Pre-filter vs Post-filter จะส่งผลอย่างมากต่อประสิทธิภาพ- Pre-filter เหมาะกับฟิลเตอร์ที่มีความจำเพาะสูง แต่ถ้าข้อมูลมีมากจะช้า
- Post-filter เร็วกว่า แต่มีโอกาส ทำให้ผลลัพธ์หลังกรองหายไปบางส่วน
- query planner ของ Postgres ไม่เข้าใจ cost model ของความคล้ายคลึงของเวกเตอร์ และเพราะข้อมูลสถิติไม่แม่นยำจึงสร้าง execution plan ที่ไม่มีประสิทธิภาพ
- ผลลัพธ์คือจำเป็นต้องใช้ วิธีแก้เฉพาะหน้าอย่าง CTE, partitioning, การเขียนคิวรีใหม่ ซึ่ง ไม่มีประสิทธิภาพเมื่อระบบขยายขนาด
การเปรียบเทียบกับฐานข้อมูลเวกเตอร์เฉพาะทาง
- Pinecone, Weaviate, OpenSearch k-NN เป็นต้น มี การเลือกกลยุทธ์การกรองอัตโนมัติ, การค้นหาแบบไฮบริด, การทำดัชนีแบบเรียลไทม์, การขยายแนวนอน ให้เป็นพื้นฐาน
- แต่ใน pgvector ต้อง ลงมือสร้างความสามารถเหล่านี้เอง ซึ่งนำไปสู่ ความซับซ้อนในการปฏิบัติการและภาระการบำรุงรักษา
- pgvectorscale ของ Timescale มี StreamingDiskANN, incremental index build, และการปรับปรุงด้านการกรอง แต่
- ไม่รองรับบน AWS RDS และยังมี ภาระในการติดตั้งและดูแลส่วนขยายเพิ่มเติม
ต้นทุนและข้อพิจารณาด้านปฏิบัติการ
- แม้ฐานข้อมูลเวกเตอร์เฉพาะทางจะเป็นบริการแบบมีค่าใช้จ่าย แต่เมื่อคำนึงถึง การจัดสรร Postgres infrastructure เกินความจำเป็น การจัดการดัชนี และเวลาทางวิศวกรรม ก็อาจ มีต้นทุนจริงถูกกว่า
- ตัวอย่างเช่น Turbopuffer เริ่มต้นที่ $64 ต่อเดือน และให้ทั้ง ความเรียบง่ายในการปฏิบัติการและความสามารถในการขยายระบบ
บทสรุปและคำแนะนำ
- pgvector ยอดเยี่ยมในเชิงเทคนิค แต่มีข้อจำกัดมากเมื่อใช้งานในสภาพแวดล้อมจริง
- ประเด็นสำคัญที่ควรพิจารณาเมื่อสร้างระบบสำหรับใช้งานจริง
- ความซับซ้อนของการจัดการดัชนี และความต้องการหน่วยความจำที่สูง
- ข้อจำกัดของ query planner ที่ทำให้การกรองไม่มีประสิทธิภาพ
- ต้นทุนของการทำดัชนีแบบเรียลไทม์ และคุณภาพที่ลดลง
- การทำให้เรื่องซับซ้อนดูง่ายเกินไปในบทความบล็อก
- เหตุผลที่ฐานข้อมูลเวกเตอร์เฉพาะทางมีอยู่ และประสิทธิภาพของมัน
- โดยสรุปแล้ว ความซับซ้อนในการปฏิบัติการมีมากกว่าความเรียบง่ายของการผสานกับ Postgres และสำหรับทีมส่วนใหญ่ การใช้ฐานข้อมูลเวกเตอร์เฉพาะทางคือทางเลือกที่สมจริงกว่า
5 ความคิดเห็น
แต่ถึงอย่างนั้น สำหรับคิวรีแบบผสม (embedding + SQL แบบดั้งเดิม) ก็ไม่มีอะไรสู้
pg_vectorได้อยู่ดีผมคิดว่าถ้าจะให้ระบบนิเวศมีสุขภาพดี ก็ควรมีเสียงโต้แย้งต่อกระแสที่ยกให้สิ่งหนึ่งครอบจักรวาลอยู่มากพอด้วย
เห็นด้วยครับ/ค่ะ สำหรับองค์กรที่ใช้งาน Postgres อยู่แล้วและกำลังเริ่มใช้ VectorDB กับข้อมูลขนาดเล็ก pgVector ถือเป็นตัวเลือกที่ยอดเยี่ยมอย่างไม่ต้องสงสัย แต่เมื่อทราฟฟิกเพิ่มขึ้นมาก โดยเฉพาะ Write Traffic ปัญหาที่ผู้เขียนบทความต้นฉบับพูดถึงก็ดูจะกลายเป็นคอขวดครับ/ค่ะ
ใช่แล้ว เพราะไม่มีอะไรสมบูรณ์แบบอยู่แล้ว ผมคิดว่าการบอกว่า "มีเรื่องเร่งด่วนอื่นอยู่" ยังพอรับได้ แต่ไม่ควรยอมรับคำพูดว่า "ระดับตอนนี้ก็เพียงพอแล้ว"
ความเห็นจาก Hacker News
เราใช้ pgvector ในโปรดักชันบนฐานข้อมูลหลายพันตัวอยู่แล้วที่ Discourse
มันถูกใช้กับ pageview ส่วนใหญ่ และฟีเจอร์ Iterative Scans ถูกเพิ่มเข้ามาในเวอร์ชัน 0.8.0 เพื่อปรับปรุงปัญหา pre/post filtering
ถ้าเป็นบริการเดี่ยว ฐานข้อมูลเวกเตอร์แบบเฉพาะทางอาจใช้ง่ายกว่า แต่ก็ไม่ใช่คำตอบสารพัดนึก
ใช้ halfvec (16bit float) สำหรับการจัดเก็บ และใช้ bit (binary vectors) สำหรับดัชนี เพื่อให้ได้ทั้งต้นทุนการจัดเก็บและประสิทธิภาพ
เราใช้ Vespa เพื่อทำการค้นหาแบบ map-reduce ในระดับโหนด
ถ้าจะทำอะไรคล้ายกันใน Postgres ก็น่าจะต้องใช้ sharding และตรรกะแอปพลิเคชันที่ซับซ้อน
การทำ reindexing หรือ metadata denormalization ก็น่าจะกินเวลามากอยู่ดี
ถึงอย่างนั้น vector DB ก็ไม่ใช่คำตอบสารพัดนึก และระบบที่รองรับ relational filtering อย่าง Vespa มีประสิทธิภาพกว่ามาก
แต่ iterative scan ไม่ใช่วิธีแก้ปัญหาในระดับรากฐาน และค่อนข้างใกล้เคียงกับการแก้ขัดชั่วคราว
ต้องเข้าใจพารามิเตอร์อย่าง ef_search, max_search_tuples และ planner ก็ยังไม่เข้าใจ cost model ของการค้นหาเวกเตอร์แบบมีการกรองได้อย่างสมบูรณ์
สุดท้ายแล้วก็เป็นเรื่องว่าคุณมีทรัพยากรพอจะจูน query planner อัจฉริยะ เอง หรือจะใช้บริการที่เชี่ยวชาญเรื่องนี้โดยเฉพาะ
วิธีที่อธิบายในงานวิจัยของ Microsoft ถูกนำไปใช้ใน pgvectorscale ของ Timescale
วิธีนี้อาจมีประสิทธิภาพกว่าการทำ pre/post filtering แบบง่ายๆ
เราได้แก้ปัญหาส่วนใหญ่ของ pgvector ที่พูดถึงในบล็อกไว้แล้วใน VectorChord
ใช้ IVF + quantization ทำให้รองรับ การอัปเดตเร็วกว่า 15 เท่า เมื่อเทียบกับ HNSW ของ pgvector
ด้วย 16vCPU และหน่วยความจำ 32GB สามารถสร้างดัชนีเวกเตอร์ 768 มิติ จำนวน 100 ล้านรายการได้ภายใน 20 นาที
สามารถทำ reindexing ได้โดยไม่สูญเสียข้อมูลด้วย
CREATE INDEX CONCURRENTLYรองรับ pre/post filtering และ การค้นหาแบบไฮบริด ที่อิง BM25 ด้วย
ดูรายละเอียดเพิ่มเติมได้ในบล็อกของ VectorChord
ดูกรณีที่เกี่ยวข้องได้ในบล็อกนี้
การสร้างดัชนีใช้หน่วยความจำมาก แต่ควบคุมได้ด้วย
maintenance_work_memการสร้างดัชนีใหม่ทำได้ด้วย
REINDEX CONCURRENTLYและการอัปเดต HNSW ก็เป็นแนวคิดคล้ายกับการอัปเดต B+treeบทความนี้ให้ความรู้สึกเหมือนอ่านเอกสารของ Postgres มาไม่ดีพอ
maintenance_work_memการทำดัชนีก็จะ ช้าลงB+tree แตะเพียงหน้า log H แต่ HNSW ต้องแก้ไขเวกเตอร์หลายพันรายการ
ถ้าจะ rebuild สิ่งนี้ ก็ต้องเตรียมความจุ DB ไว้ มากกว่าสองเท่า และยังส่งผลกระทบต่อ workload อื่นด้วย
REINDEX CONCURRENTLYก็ใช้เวลานานการแทรกข้อมูลใน HNSW แม้จะมี complexity ต่ำ แต่ต้นทุนค่าคงที่สูง จึงเป็นภาระมากในทางปฏิบัติ
maintenance_work_memแต่การกิน RAM ระดับ GB เป็นเวลาหลายชั่วโมงระหว่างรันงานจริงก็มีความเสี่ยงREINDEX CONCURRENTLYก็ใช้ดิสก์เพิ่ม 2-3 เท่าและกระทบต่อประสิทธิภาพสุดท้ายประเด็นสำคัญไม่ใช่ว่า Postgres ขาดฟีเจอร์ แต่คือ ความซับซ้อนในการปฏิบัติการระบบ ที่สูง
vector DB แบบเฉพาะทางจัดการเรื่องพวกนี้ให้อัตโนมัติ จึงมีประสิทธิภาพกว่ามากสำหรับทีมขนาดเล็ก
การที่ Turbopuffer เริ่มต้นที่ $64 ต่อเดือน อธิบายได้ว่าทำไม pgvector ถึงได้รับความนิยม
ถ้ารู้สึกว่า $64 แพงก็ใช้ pgvector ได้ แต่ถ้ารู้สึกว่าราคานี้ไม่แพง ก็แปลว่าคุณมี use case ที่ซับซ้อนอยู่แล้วและ vector DB แบบเฉพาะทาง น่าจะเหมาะกว่า
แม้ในกลุ่มลูกค้า GCP ก็เห็นหลายกรณีที่ใช้ pgvector HNSW ในโปรดักชัน
แต่ในทางปฏิบัติจะเหมาะแค่ช่วงขนาด 0 ถึง 10 ล้านเวกเตอร์
ต้องพิจารณาเรื่อง ETL, operational overhead, ปัญหาความสอดคล้องของข้อมูล ฯลฯ
ถ้าต้องการธุรกรรม การค้นหาแบบไฮบริด และ latency ต่ำ AlloyDB + ScaNN เป็นตัวเลือกที่ดีกว่า
(เพื่ออ้างอิง ฉันเป็นคนสร้าง ScaNN ที่ GCP และตอนนี้เป็นผู้นำ AlloyDB Semantic Search)
หลักการพื้นฐานของฉันคือ YAGNI
ลดจำนวนบริการให้น้อยที่สุดเท่าที่ทำได้ และถ้ามีปัญหาค่อยเพิ่มของใหม่ตอนนั้น
ถ้า Postgres เพียงพอก็ใช้ต่อไป และถ้าไม่พอ ตอนนั้นเราจะรู้ได้ชัดว่าต้องการอะไร
เรื่องอย่างการเขียนเวกเตอร์แบบเรียลไทม์ หรือการผสาน SQL filter กับการค้นหาความคล้ายคลึงกัน อาจดูเล็กน้อย แต่จริงๆ แล้วเป็นฟีเจอร์จำเป็น
เมื่อสเกลใหญ่ขึ้น ข้อจำกัดเหล่านี้จะกลายเป็นปัญหาร้ายแรง
เวลาใช้โมเดล vector embedding มันมีประโยชน์มากแม้จะไม่ใช่ชุดข้อมูลขนาดใหญ่
ตัวอย่างเช่น การค้นหาเอกสาร หรือ การค้นหาข้อมูลสินค้า
ฉันอยากได้อินเทอร์เฟซที่เมื่อเขียนเอกสารเหมือนใช้ไฟล์ซิสเต็มแล้วดัชนีอัปเดตให้อัตโนมัติ
เพราะแบบนั้นบริการอย่าง Amazon S3 Vectors(ลิงก์) จึงน่าสนใจ
อยากรู้ว่าประสบการณ์ใช้งานจริงเป็นอย่างไร
ดูทิวทอเรียลที่เกี่ยวข้องได้ในบทความนี้
ปัญหาที่กล่าวถึงถูกแก้ไปแล้ว และฉัน ชอบใช้ PGVector มากกว่า
ถ้า Postgres สามารถแทน Kafka และรองรับ 100,000 events ต่อวินาทีได้ PGVector ก็น่าจะเพียงพอแทน vector DB แบบเฉพาะทางอย่าง Chroma ได้เหมือนกัน
ลิงก์อ้างอิง
use case ของ pgvector ส่วนใหญ่เป็นชุดข้อมูลขนาดเล็กอย่าง “แชตบอตที่อิงเอกสารเทคนิค”
ข้อมูลไม่ได้เปลี่ยนบ่อย และไม่มี multitenancy จึงมีปัญหาเรื่อง filtering น้อย
ในทางกลับกัน Chroma รองรับ SPANN, SPFresh, การค้นหาแบบไฮบริด และเป็น โอเพนซอร์ส Apache 2.0 เต็มรูปแบบ
ด้วยโมเดลคิดค่าบริการตามการใช้งาน ต้นทุนอาจอยู่เพียงประมาณ 1 ดอลลาร์ต่อเดือน
Redis Vector Sets ที่ฉันพัฒนามาตลอด 1 ปีที่ผ่านมาแก้ปัญหาเหล่านี้ได้
มีการ implement HNSW โดยตรง จึงรองรับ การอัปเดตแบบเรียลไทม์ และเมื่อมีการลบ หน่วยความจำก็ถูกคืนกลับทันที
รองรับความเร็วการแทรกระดับหลายแสน ops/sec และการค้นหาระดับ 50,000 ops/sec
รองรับ quantization โดยปริยาย จึงมีประสิทธิภาพด้านหน่วยความจำสูงด้วย
สรุปรายละเอียดไว้ในเอกสาร README
ตอนนี้ฟังก์ชัน replication ก็ผ่านการทดสอบครบถ้วนแล้ว