بحث واحد في الدليل.
مسح متجاور واحد.
البحث المتجهي المفلتَر عادةً تشتيت وتجميع عبر فهرس لا يعلم شيئاً عن فلترك. Telys يمتلك التخطيط الفيزيائي عوضاً عن ذلك: على مفتاح القسم، أقرب الجيران حيث المفتاح يساوي x هو بحث O(1) في الدليل ومسح تسلسلي واحد لكتلة متجاورة. تستعرض هذه الصفحة وقت التشغيل المشحون اليوم، ثم البنية التي يتقارب نحوها — مُصنَّفة كمواصفة.
المحرك يمتلك موضع كل متجه.
تُعلن المجموعة عن partition_by عند الإنشاء، ويتبع التخطيط المفتاح. المقطع الأساسي مُجمَّع حسب القسم — كل مفتاح يُعيَّن إلى شريحة متجاورة واحدة — وتجلس الكتابات الحديثة بجانبه في دلتا قابلة للتغيير بشكل Arrow.
مُجمَّع بالأقسام
متجهات مُخزَّنة مرتبة حسب مفتاح القسم، بحيث يكون كل قسم كتلة متجاورة واحدة. الاستعلام المحدود النطاق يقرأ تسلسلاً واحداً من الذاكرة، لا صفوفاً مبعثرة عبر فهرس.
O(1) مفتاح → شريحة
يربط الدليل كل قيمة قسم بـ (offset, length) في المقطع الأساسي. حل الفلتر بحث في قاموس، لا اجتياز فهرس.
كتابات بشكل Arrow
add و upsert يُلحقان هنا، كل صف مختوم بـ LSN كتابة رتيب. الدلتا قابلة للاستعلام فوراً وتتحد مع الشريحة الأساسية عبر مسار مسح واحد.
ما ينفذه استعلام محدود النطاق.
col.search(qvec, where={"tenant_id": "acme"}, top_k=10)
يُسمّي الفلتر مفتاح القسم الذي أُنشئت به المجموعة.
بحث O(1): قيمة القسم تُحل إلى (offset, length) في المقطع الأساسي. لا توليد مرشحين، لا نقطة دخول للرسم البياني.
تسجيل دقيق بـ SIMD على كتلة تسلسلية واحدة. الاسترجاع على هذا المسار 1.0 — إنه مسح، لا تقريب. p50/p95 المقيسة لهذه الخطوة مُنشورة في صفحة المعايير، كل قيمة مرتبطة ببوابة الاسترجاع والجهاز.
تمر صفوف المفتاح ذاته في دلتا Arrow عبر المسار نفسه. تصبح الكتابة مرئية للاستعلام التالي مباشرةً.
يُصفّي الضرب عند LSN اللقطة: لا تظهر الإصدارات المحذوفة أو المُستبدَلة. يعود Top-k مرفقاً بحمولة explain.
تسلك الأقسام الضخمة مساراً معلناً: يضع build_ivf فهرس IVF لكل قسم يتجاوز عتبة الصفوف، وتُوجَّه الاستعلامات عبره مع إعادة ترتيب دقيقة — معايَرة وفق حد استرجاع أدنى، ومُسمّاة في الخطة.
كل نتيجة تُسمّي خطتها.
يُعيد explain=True الخطة الفيزيائية التي سلكها الاستعلام فعلاً. على مفتاح القسم تحصل على مسح الشريحة المتجاورة. تُعلن الأقسام الضخمة مسار IVF. تتراجع المرشّحات خارج المفتاح إلى scatter-gather — والحمولة تشرح السبب.
hits = col.search(qvec, where={"tenant_id": "acme"}, top_k=10, explain=True)
hits["explain"]["plan"]
# on the partition key → "PartitionSliceExactF32" # one contiguous slice, exact, recall 1.0
# oversized partition → "PartitionIVFRerankF32" # per-partition IVF + exact rerank
# off-key filter → "ScatterGatherExact" # fallback — and it says why:
hits["explain"]["fallback_reason"]
# "path is not the physical partition key"لا شيء يُستبدَل في مكانه. الإصدارات تُستعاض عنها.
نموذج الكتابة هو MVCC الإلحاقي فقط. يكتب upsert إصداراً جديداً للمعرّف المنطقي ويُعلّم السابق مُستبدَلاً؛ يضع delete علامة حذف عند LSN الحذف؛ يُثبّت snapshot() عرض قراءة متسقاً؛ يطوي compact() الدلتا في القاعدة ويحذف ما لا تراه أي لقطة.
col.upsert(vectors, ids=ids, metadata=metadata) # a new version; the prior one is superseded col.delete(["doc-41"]) # tombstone at a delete LSN — no in-place erase lsn = col.snapshot() # pin a consistent read view at an LSN col.compact() # fold delta into base; drop superseded rows col.build_ivf(min_rows=20000, target_recall=0.98)
| الاستدعاء | ما يفعله |
|---|---|
| إضافة / إضافة_نصوص | إدراج صفوف جديدة. تُرفض المعرّفات المكررة — الصف الفيزيائي الثاني لمعرّف منطقي واحد يستلزم upsert، عن قصد. |
| رفع / رفع_نصوص | كتابة إصدار جديد للمعرّف المنطقي؛ يُستبدَل الإصدار السابق ولا يُعاد الكتابة فوقه. |
| بحث / بحث_نص | Top-k مع تصفية. يُرفق explain=True الخطة الفيزيائية بالنتيجة. |
| delete | وضع علامة حذف على الصفوف المنطقية عند LSN الحذف. |
| compact | طي الدلتا في المقطع الأساسي؛ حذف الإصدارات المُعلَّمة والمُستبدَلة. |
| build_ivf | بناء IVF لكل قسم يتجاوز عتبة الصفوف، معايَراً وفق حد استرجاع أدنى. |
| snapshot | إعادة LSN يُثبّت عرض قراءة متسقاً. |
| save / stats | حفظ المجموعة على القرص؛ الإبلاغ عن أعداد الصفوف والأقسام وحقائق التخطيط. |
كل ما يلي مواصفة، لا مرجع API منشور. إنه الركيزة التي يتقارب إليها وقت التشغيل. الواجهة المواجهة للـ SDK مجمّدة، فالاستبدال من تحتها غير مرئي للمستدعين.
مخطط واحد. IR مسطّح واحد. منفّذ واحد.
تنزل ثلاث واجهات أمامية إلى مخطط واحد يُصدر تمثيلاً وسيطاً فيزيائياً مسطّحاً واحداً، يُنفّذه منفّذ Mojo المتجهي مباشرةً فوق مخازن Arrow.
نموذج الذاكرة (remember · recall · as_of)، وواجهة الاستعلام (point_get · scan · search · hybrid_search)، والنسيج. عقد دخول واحد؛ لا محرك لكل API.
التخطيط المنطقي والفيزيائي في مكان واحد. تُقدَّر الانتقائية من إحصاءات المقاطع؛ الخطة صريحة وتُعاد مع النتيجة.
مصفوفة مسطّحة من المشغّلات مرتبطة بفتحات صحيحة. السجل بين المشغّلات مجموعة صفوف — خريطة بت، أو معرّفات صفوف مرتّبة، أو متجه اختيار.
تنفيذ متجهي فوق مخازن Arrow ومصفوفات مرشّحي FAISS. يبقى المسار الساخن SIMD خارج Python؛ تُفكّ صفحات Parquet المضغوطة في مخازن مؤقتة أولاً.
طبقة التحوير
سجل كتابة مسبقة للمتانة والترتيب، ودلتا Arrow قابلة للتعديل للرؤية الفورية — طبقة الجدول التي يفتقر إليها Parquet وحده.
مختومة، غير قابلة للتعديل
مقاطع عمودية مضغوطة ومتينة. تقود إحصاءات التذييل تقليم المقاطع ومجموعات الصفوف؛ الملفات المختومة لا تُعدَّل أبداً.
FAISS ANN
فهارس FAISS لكل مقطع، مرتبطة بمجموع تحقق المقطع وإصداره، مُعيَّنة للقراءة فقط مع عمر مرتبط بلقطة القراءة.
التقليم والمعجمي
خرائط المناطق وفلاتر بلوم وخرائط البت للتقليم؛ ملحق BM25 للاسترجاع المتفرق ودمج الدرجات.
SCAN FILTER PROJECT POINT_GET RANGE_GET AGGREGATE TOP_K HASH_JOIN HASH_GROUP_BY SORT ANN_SEARCH SPARSE_SEARCH FUSE RERANK MATERIALIZE
WAL أولاً. مرئي فوراً. يُختم في الخلفية.
إطارات إلحاقية فقط مع مجاميع تحقق وLSNs رتيبة. تُعيد الاسترداد تشغيل السجلات بعد آخر LSN مختوم وتقطع عند أول مجموع تحقق خاطئ.
تحط الكتابة في الدلتا القابلة للتعديل وتصبح قابلة للاستعلام فوراً — تتحد المقاطع المختومة والدلتا عبر مسار مسح واحد.
عند تجاوز حدّ الحجم أو الصفوف أو العمر، يُرتَّب الدلتا ويُكتب كمقطع Parquet مع ملف .vidx والملفات المرافقة، ثم يُنشر عبر تبديل ذري للمانيفست.
تدمج العمليات الخلفية المقاطع الصغيرة معاً، وتحذف الصفوف المحذوفة منطقياً، وتُعيد بناء الملفات المرافقة — بميزانية محكومة، فتظل عمليات النشر على الجهاز هادئة.
المقاطع المختومة لا تُعدَّل أبداً. تثبّت القراءة (لقطة المانيفست، LSN)؛ يختم الكتّاب مقاطع جديدة ويبدّلون المانيفست دون الإخلال بالقراءات الجارية. تنتظر عملية جمع المهملات أقدم لقطة حية.
الفلتر هو من يختار الخطة، لا العكس.
ANN المصفّى هو تخطيط تكيّفي قائم على الانتقائية: يقدّر المخطط عدد الصفوف التي تنجو من الفلتر استناداً إلى إحصاءات المقاطع، ثم يختار أرخص استراتيجية تحافظ على عقد الاستدعاء.
تصفية مسبقة → دقيق
فلترة عددية أو ببت-ماب أولاً، ثم تسجيل SIMD دقيق على الصفوف الناجية. دون حدّ معين من الصفوف يُتخطى ANN كلياً — مسح دقيق، استدعاء 1.0.
اجتياز Allow-bitmap
يحمل اجتياز ANN allow-bitmap، فلا يُظهر الفهرس إلا الصفوف التي يقبلها الفلتر.
ANN → تصفية لاحقة
ANN أولاً مع جلب زائد تكيّفي، ثم فلترة لاحقة. الفلتر يحذف القليل، فتوليد المرشحين هو المحرّك.
بوابات الصحة تسبق أي رقم أداء.
يُتحقق من وقت التشغيل المُشحون بمجموعات تكافؤ تُشغَّل على كلا تطبيقَي المحرك، وكل استعلام قادر على تسمية الخطة الفيزيائية التي اتخذها. هذا هو ترتيب العمليات هنا: بوابات الصحة أولاً، القياس ثانياً.
تُنشر المعايير ضمن عقد عدالة — استرجاع متطابق، عتاد متطابق، نتائج مفصولة حسب النقل، مع الإفصاح عن الفوز والتعادل والخسارة. أول النتائج المقيسة متاحة الآن في صفحة المعايير، كل رقم مُرفَق بشروطه الكاملة: العتاد والمجموعة البيانية والبُعد والانتقائية والاسترجاع والنقل. كل مضاعف يبقى فرضية خارج الشروط المذكورة بجانبه.