- Tantivy เป็นไลบรารีเอนจินค้นหาแบบฟูลเท็กซ์ความเร็วสูงที่เขียนด้วย Rust และมีลักษณะใกล้เคียงกับ crate สำหรับใช้สร้างเอนจินค้นหา มากกว่าจะเป็นเซิร์ฟเวอร์ค้นหาที่เสร็จสมบูรณ์พร้อมใช้งาน
- การออกแบบได้รับแรงบันดาลใจอย่างมากจาก Apache Lucene และหากกำลังมองหาเซิร์ฟเวอร์ทางเลือกแทน Elasticsearch หรือ Apache Solr ก็แนะนำให้ดูเอนจินค้นหาแบบกระจายศูนย์ Quickwit ที่สร้างอยู่บน Tantivy
- ความสามารถประกอบด้วยการค้นหาแบบฟูลเท็กซ์, การให้คะแนน BM25, คำค้นภาษาธรรมชาติ, การค้นหาวลี, incremental indexing, multithreaded indexing, mmap directory, การบีบอัดจำนวนเต็มด้วย SIMD, faceted search, ฟิลด์ JSON, Aggregation Collector เป็นต้น
- ทำงานบน stable Rust รองรับ Linux, macOS, Windows และระบุว่าใช้เวลาเริ่มต้น ต่ำกว่า 10ms จึงเหมาะกับเครื่องมือบรรทัดคำสั่ง
- การค้นหาแบบกระจายศูนย์อยู่นอกขอบเขตของ Tantivy และการแก้ไขเอกสารต้องลบเอกสารเดิมแล้วทำดัชนีใหม่ โดยเอกสารใหม่จะค้นหาได้หลัง
commit จากนั้นต้องรีโหลด IndexReader และรับ Searcher ตัวใหม่
ตำแหน่งและแนวทางการออกแบบของ Tantivy
- Tantivy เป็นไลบรารีเอนจินค้นหาแบบฟูลเท็กซ์ความเร็วสูงที่เขียนด้วย Rust
- ไม่ใช่เซิร์ฟเวอร์เอนจินค้นหาที่รันได้ทันทีแบบ Elasticsearch หรือ Apache Solr แต่เป็น crate ที่สามารถนำไปใช้สร้างเอนจินค้นหาลักษณะนั้นได้
- ในแง่การออกแบบ มันใกล้เคียงกับ Apache Lucene มากกว่า และได้รับแรงบันดาลใจอย่างมากจากแนวทางของ Lucene
- หากกำลังมองหาทางเลือกแทน Elasticsearch หรือ Apache Solr ก็แนะนำให้ดูเอนจินค้นหาแบบกระจายศูนย์ Quickwit ที่สร้างอยู่บน Tantivy
ประสิทธิภาพและเบนช์มาร์ก
- Tantivy มี benchmark ที่แยกประสิทธิภาพตามประเภทของคำค้นและคอลเลกชัน
- ผลเบนช์มาร์กอาจแตกต่างกันตามลักษณะของคำค้นและภาระงาน
- ดูรายละเอียดของเบนช์มาร์กได้ที่รีโพซิทอรี search-benchmark-game
- ตาม FAQ ในเบนช์มาร์กด้าน search latency นั้น Tantivy เร็วกว่า Lucene โดยเฉลี่ยประมาณ 2 เท่า
ความสามารถด้านการค้นหาและการทำดัชนี
-
ความสามารถด้านการค้นหา
- การค้นหาแบบฟูลเท็กซ์
- การให้คะแนนแบบ BM25 เช่นเดียวกับ Lucene
- รองรับคำค้นภาษาธรรมชาติ:
(michael AND jackson) OR "king of pop"
- รองรับการค้นหาวลี:
"michael jackson"
- range query
- faceted search
- JSON Field
- Aggregation Collector: histogram, range buckets, average, stats metrics
-
ความสามารถด้านการทำดัชนี
- รองรับ incremental indexing
- รองรับ multithreaded indexing
- ระบุว่าการทำดัชนี Wikipedia ภาษาอังกฤษใช้เวลาไม่ถึง 3 นาทีบนเดสก์ท็อป
- ตั้งค่าการทำดัชนีได้ผ่าน term frequency แบบเลือกได้และ position indexing
- รองรับ LogMergePolicy with deletes
- มี Searcher Warmer API
-
การจัดเก็บและฟิลด์
- รองรับ mmap directory
- รองรับ fast fields แบบ single-valued และ multivalued สำหรับ u64, i64, f64
- รองรับ fast fields ของ
&[u8]
- รองรับฟิลด์ text, i64, u64, f64, dates, ip, bool, hierarchical facet
- การบีบอัด document store รองรับ LZ4, Zstd, None
โทเค็นไนเซอร์และการรองรับภาษา
- โทเค็นไนเซอร์สามารถตั้งค่าได้ และรองรับ stemming สำหรับ 17 ภาษาในตระกูลละติน
- ยังรองรับโทเค็นไนเซอร์จาก third party ด้วย
- เมื่อต้องการพัฒนาโทเค็นไนเซอร์สำหรับ Tantivy จำเป็นต้องพึ่งพา crate
tantivy-tokenizer-api
สภาพแวดล้อมการทำงานและวิธีเริ่มต้น
- Tantivy ทำงานบน stable Rust
- ระบบปฏิบัติการที่รองรับคือ Linux, macOS, Windows
- ใช้เวลาเริ่มต้น ต่ำกว่า 10ms จึงเหมาะกับเครื่องมือบรรทัดคำสั่ง
- เอกสารเริ่มต้น
- การ build และทดสอบบนเครื่องทำได้ด้วยคำสั่งต่อไปนี้
git clone https://github.com/quickwit-oss/tantivy.git
cd tantivy
cargo test
ความสามารถที่อยู่นอกขอบเขตและโมเดลการเปลี่ยนแปลงข้อมูล
- การค้นหาแบบกระจายศูนย์ อยู่นอกขอบเขตของ Tantivy
- หากต้องการการค้นหาแบบกระจายศูนย์ แนะนำให้ดู Quickwit
- ข้อมูลของ Tantivy เป็นแบบ immutable
- หากต้องการแก้ไขเอกสาร ต้องลบเอกสารเดิมแล้วทำดัชนีใหม่
- เอกสารที่กำลังทำดัชนีจะค้นหาได้หลังจากมีการเรียก
commit ใน IndexWriter
IndexReader เดิมต้องถูกรีโหลดเพื่อให้สะท้อนการเปลี่ยนแปลง
- การเปลี่ยนแปลงจะมองเห็นได้เฉพาะใน
Searcher ตัวใหม่ที่ดึงมาเท่านั้น
ไบน์ดิงและกรณีการใช้งาน
- ไบน์ดิงที่ใช้ได้จากภาษาอื่น
- Python: tantivy-py
- Ruby: tantiny
- ยังหาไบน์ดิงอื่นได้บน GitHub แต่การดูแลรักษาอาจไม่ต่อเนื่องนัก
- ตัวอย่างการใช้งาน Tantivy
- seshat: ฐานข้อมูล/ตัวทำดัชนีข้อความของ Matrix
- tantiny: การค้นหาแบบฟูลเท็กซ์ขนาดเล็กสำหรับ Ruby
- lnx: เอนจินค้นหาที่ปรับตัวได้ รองรับการพิมพ์ผิด และมี REST API
- Bichon: ตัวเก็บถาวรอีเมล Rust ประสิทธิภาพสูงขนาดเบาพร้อม WebUI
- บริษัทที่ระบุว่าใช้งาน Tantivy ได้แก่ Etsy, ParadeDB, Nuclia, Humanfirst.ai, Element.io
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
คนที่สร้างไลบรารีนี้สุดยอดจริง ๆ ปีที่แล้วตอนผมแทนที่โค้ดเบส Python2 AppEngine เก่า ๆ ที่ปล่อยทิ้งไว้เป็นเวลานาน ผมก็สร้าง https://progscrape.com [1] ขึ้นมาใหม่บนสิ่งนี้ เป็นไลบรารีที่ยอดเยี่ยมและเร็วมาก
มันสามารถทำดัชนีสตอรีครบ 1 ล้านรายการบน Raspberry Pi ได้ภายในไม่กี่วินาที
ผมรันบริการค้นหาแบบ full-text บน Pi ที่บ้าน และแม้โหลดสูงสุดจะมีเพียงไม่กี่ rps จึงไม่ได้มากนัก แต่ CPU ก็แทบไม่เคยกระโดดเกินไม่กี่เปอร์เซ็นต์ ผมทดสอบโหลดการค้นหาบน Pi ได้ราว 100rps และมันก็รับไหว เป็นไลบรารีที่มีประโยชน์มากเพราะแทบจะเอาไปเสียบแทนได้ตรง ๆ ทีมก็ตอบสนองต่อบั๊กรีพอร์ตได้เร็วมาก และมีบั๊กน้อยมากด้วย
ถ้าอยากดูว่าการตอบสนองของการค้นหาบนอุปกรณ์เล็ก ๆ แบบนี้เป็นอย่างไร ให้กดที่ป้ายกำกับของแต่ละสตอรี มันแทบจะ query ได้ทันที และกำลังยิงไปที่ search shard สูงสุด 10 ปี * 12 เดือน: https://progscrape.com/?search=javascript
ถ้าเป็นโปรเจ็กต์สมัยใหม่ ผมแนะนำให้ดูตัวนี้แทน Lucene มันสเกลได้ดีขนาดนี้แม้บน ARM64 เครื่องเล็ก ๆ ดังนั้นบนเซิร์ฟเวอร์ที่ใหญ่กว่าน่าจะให้ประสบการณ์ที่ดียิ่งกว่า
[1] https://github.com/progscrape/progscrape
ผมอยากให้ผู้ใช้ค้นหาในแบ็กอัปของตัวเองได้ และเพราะใช้ Rust อยู่แล้ว Tantivy เลยดูเหมาะพอดี ความเร็วในการทำดัชนีอีเมลหนึ่งฉบับเร็วมากจนไม่จำเป็นต้องย้ายไปไว้ใน thread แยก และการค้นหาอีเมลหลายพันฉบับก็ดูไม่มีปัญหา
ถ้าแอปพลิเคชัน Rust ของคุณต้องการระบบค้นหา Tantivy ก็น่าลองดู
Error: PersistError(UnexpectedError("Storage fetch panicked"))แสดงอยู่โดยพื้นฐานแล้วสิ่งที่ต้องการมีแค่ full-text search
ช่วงนี้ผมเพิ่งเจอ Tantivy ภายใน ParadeDB ซึ่ง ParadeDB เป็น ส่วนขยาย Postgres ที่พยายามมาแทน Elastic
https://github.com/paradedb/paradedb/blob/dev/pg_search/Carg...
รู้จักจากการฟัง “Extending Postgres for High Performance Analytics (with Philippe Noël)”
https://www.youtube.com/watch?v=NbOAEJrsbaM
และมันยังอยู่ในโปรเจ็กต์หลักอย่าง Quickwit ด้วย ซึ่งเป็นโปรเจ็กต์ที่จัดการทั้งล็อก การติดตาม และในไม่ช้าก็เมตริกด้วย
https://github.com/quickwit-oss/quickwit
ผมเคยลองใช้ Quickwit คู่กับ ClickHouse ในโปรเจ็กต์ส่วนตัวด้านการค้นหาแบบหลายภาษา แล้วมันดีจนน่าประหลาดใจ ในที่สุดก็มีชุดผสมที่พอใช้ได้จริงสำหรับภาษาจีน ญี่ปุ่น และเกาหลี
https://quickwit.io/docs/guides/add-full-text-search-to-your...
to_tsvectorของ PostgreSQL ไม่เคยเข้ากับ use case ของผมได้ดีจริง ๆ เลยSELECT * FROM dump WHERE to_tsvector('english'::regconfig, hh_fullname) @@ to_tsquery('english'::regconfig, 'query');หวังว่ามันจะไปได้ดี ถ้าบทความไหนมีคำว่า Tantivy อยู่ ผมคงกดโหวตให้อัตโนมัติ
ไม่นานมานี้เรา deploy Quickwit ซึ่งสร้างบน Tantivy และทำโดยทีมเดียวกัน ไปใช้งาน production เพื่อทำดัชนีออบเจ็กต์หลายพันล้านรายการ และพอใจมาก ความเร็วในการทำดัชนี ยอดเยี่ยม และ latency ของ query ก็แข่งขันได้
ที่สำคัญที่สุดคือ การแยก compute ออกจาก storage ให้คุณค่ามหาศาล มันทำให้เราสามารถเปิดบริการค้นหาใหม่บนออบเจ็กต์หลายพันล้านรายการใน object storage และทำ aggregation ที่ซับซ้อนได้ โดยไม่ต้องจ่ายค่าเซิร์ฟเวอร์ประสิทธิภาพสูงที่ต้องรันยาว ๆ ซึ่งทำให้ use case ใหม่ที่เดิมคงมีต้นทุนสูงมากกลายเป็นไปได้
เมื่อ use case ใหญ่พอที่จะคุ้มกับเซิร์ฟเวอร์ประสิทธิภาพสูง Quickwit ก็ยังมีตัวเลือกให้ cache ข้อมูลไว้ในแต่ละเซิร์ฟเวอร์เพื่อเพิ่มประสิทธิภาพด้วย
โบนัสก้อนใหญ่อีกอย่างคือทีมใน Discord ช่วยเหลือได้เร็วและเป็นมิตรมาก
แหล่งข้อมูลอีกอย่างคือ ดัชนีค้นหา trigram ที่เขียนด้วย Go และใช้ใน etsy/hound[0] โดยอิงจากบทความและโค้ดของ Russ Cox ชื่อ “Regular Expression Matching with a Trigram Index”[1]
[0] https://github.com/hound-search/hound
[1] http://swtch.com/~rsc/regexp/regexp4.html
ทางเลือกแทน Lucene ก็มี use case ที่แตกต่างกันไปตามความต้องการ
สิ่งที่ต้องระวังคือยัง เพิ่ม/ลบฟิลด์ ไม่ได้: https://github.com/quickwit-oss/tantivy/issues/470
วิธีเดียวที่จะเพิ่มฟิลด์ได้คือทำดัชนีข้อมูลทั้งหมดใหม่ไปยังดัชนีค้นหาอื่น
เจอ Tantivy ระหว่างมองหาทางเลือกแทน Meilisearch ที่ส่งข้อมูล telemetry โดยค่าเริ่มต้น มันใกล้เคียงกับ ตัวสร้างเสิร์ชเอนจิน มากกว่าจะเป็นเสิร์ชเอนจินโดยตัวมันเอง แต่การตั้งค่าดูค่อนข้างเรียบง่าย [0]
[0]: https://github.com/quickwit-oss/tantivy-cli
Java SDK ของ Meilisearch ก็ดีเหมือนกัน ไม่ต้องใช้ CLI หรือคอนฟิกด้วยมือ แค่ชี้ไปที่ database entity ก็ทำดัชนีได้ทั้งตาราง
ถ้า Tantivy มีแนวทางแบบนั้นด้วยก็คงดี
Tantivy ยังถูกใช้เพื่อให้ความสามารถด้าน full-text search ในผลิตภัณฑ์ ฐานข้อมูลเวกเตอร์ ที่น่าสนใจชื่อ LanceDb ด้วย: https://lancedb.github.io/lancedb/fts/
ตอนที่ดูครั้งล่าสุดยังทำได้ผ่าน Python binding เท่านั้น แต่เข้าใจว่ากำลังจะทำ Rust binding แบบเนทีฟเพื่อรองรับแพลตฟอร์มอื่น
เมื่อหลายปีก่อนเริ่มโปรเจกต์ส่วนตัวขึ้นมาเพราะ Elasticsearch เป็น สัตว์ประหลาดกินทรัพยากร ที่น่าหงุดหงิดสุด ๆ แม้แต่เครื่องส่วนตัวของผมยังมีทรัพยากรมากกว่าที่สตาร์ตอัปฐานะดีหลายแห่งจัดให้ผลิตภัณฑ์ของตัวเองเสียอีก
เหตุผลที่เลือก Tantivy มีสองข้อ อย่างแรกคืออยากทำทุกอย่างด้วย Rust และอีกข้อก็คือ Tantivy เอง ประสิทธิภาพให้ 10/10 เอกสารยอดเยี่ยมมาก และประสบการณ์ใช้งานไลบรารีก็ดีมาก
น่าเสียดายที่ขอบเขตโปรเจกต์ใหญ่เกินกว่าจะทำคนเดียวในเวลาว่างไหว เลยต้องเลิกไป แต่ถึงอย่างนั้น Tantivy ก็ยอดเยี่ยมจริง ๆ
ติดตาม Tantivy มาสักพักแล้ว ความ มุ่งมั่นไม่ยอมแพ้ ของผู้ก่อตั้งและประสิทธิภาพที่ Tantivy ทำได้ในช่วงหลังน่าประทับใจมาก
ขอปรบมือดัง ๆ ให้ทั้งทีม เชื่ออย่างยิ่งว่าพวกเขาจะไปถึงเป้าหมาย
ในฐานะคนที่ใช้ Lucene กับ Solr มาเยอะ สิ่งที่อยากได้มากที่สุดคือ การรองรับการอัปเกรด ปกติดัชนีของ Lucene, Solr และ ES มักอัปเกรดไปเวอร์ชันใหม่ไม่ได้ บางกรณีก็พอทำได้ แต่ขอไม่นับเพื่อความสะดวก
ในโปรเจกต์ขนาดใหญ่ การทำดัชนีใหม่มีค่าใช้จ่ายสูงมาก และบางครั้งก็แทบเป็นไปไม่ได้
บางกรณีก็มีโอกาสสูงมากที่จะเป็นไปไม่ได้จริง ๆ เช่น เมื่ออัลกอริทึมการทำดัชนีของชนิดข้อมูลในฟิลด์ดัชนีแบบ lossy เปลี่ยนไป แต่ในหลายกรณีข้อมูลทุกอย่างยังอยู่ครบ ดังนั้นถ้าระบุดัชนีแบบนั้นและอัปเกรดได้ก็คงดีมาก