BITMAP
الفهرسة باستخدام الخرائط البتية هي تقنية فهرسة فعالة مصممة لتحسين أداء الاستعلامات على الحقول العددية ذات الكاردينالية المنخفضة. تشير الكاردينالية إلى عدد القيم المتميزة في الحقل. وتُعتبر الحقول التي تحتوي على عدد أقل من العناصر المتميزة ذات كاردينالية منخفضة.
يساعد هذا النوع من الفهارس في تقليل وقت استرجاع الاستعلامات القياسية من خلال تمثيل قيم الحقول بتنسيق ثنائي مضغوط وإجراء عمليات بتية فعالة عليها. مقارنةً بأنواع الفهارس الأخرى، تتميز فهارس الصور النقطية عادةً بكفاءة أعلى في استخدام المساحة وسرعات استعلام أسرع عند التعامل مع الحقول ذات الكاردينالية المنخفضة.
نظرة عامة
يجمع مصطلح «الخريطة البتية» (Bitmap) بين كلمتين: «البت» (Bit) و«الخريطة» (Map). يمثل البت أصغر وحدة من البيانات في الكمبيوتر، والتي لا يمكنها إلا أن تحمل قيمة 0 أو 1. أما «الخريطة»، في هذا السياق، فتشير إلى عملية تحويل البيانات وتنظيمها وفقًا للقيمة التي يجب تعيينها لـ 0 و1.
يتكون فهرس الصورة النقطية من مكونين رئيسيين: الصور النقطية والمفاتيح. تمثل المفاتيح القيم الفريدة في الحقل المفهرس. لكل قيمة فريدة، توجد صورة نقطية مقابلة لها. يساوي طول هذه الصور النقطية عدد السجلات في المجموعة. كل بت في الصورة النقطية يقابل سجلًا في المجموعة. إذا كانت قيمة الحقل المفهرس في السجل مطابقة للمفتاح، يتم تعيين البت المقابل إلى 1؛ وإلا، يتم تعيينه إلى 0.
لنفترض وجود مجموعة من المستندات تحتوي على الحقلين «الفئة» و«عام». نريد استرداد المستندات التي تندرج ضمن فئة «التكنولوجيا » والمتاحة «للجمهور». في هذه الحالة، تكون مفاتيح فهارس الصور النقطية لدينا هي «التكنولوجيا » و«عام».
الصورة النقطية
كما هو موضح في الشكل، فإن فهارس الصور النقطية لـ «Category» و«Public» هي:
Tech: [1, 0, 1, 0, 0]، مما يشير إلى أن المستندين الأول والثالث فقط يندرجان ضمن فئة Tech.
«Public»: [1, 0, 0, 1, 0]، مما يشير إلى أن المستندين الأول والرابع فقط متاحان للجمهور.
للعثور على المستندات التي تتطابق مع كلا المعيارين، نقوم بإجراء عملية «AND» بتية على هاتين الخريطتين البتيتين:
- «Tech» و «Public»: [1, 0, 0, 0, 0]
تشير الصورة النقطية الناتجة [1, 0, 0, 0, 0] إلى أن الوثيقة الأولى فقط (ID 1) هي التي تستوفي كلا المعيارين. باستخدام الفهارس النقطية وعمليات البتات الفعالة، يمكننا تضييق نطاق البحث بسرعة، مما يلغي الحاجة إلى مسح مجموعة البيانات بأكملها.
إنشاء فهرس خريطة بتية
لإنشاء فهرس صورة نقطية في Milvus، استخدم الطريقة ` create_index() ` وقم بتعيين المعلمة ` index_type ` إلى ` "BITMAP"`.
from pymilvus import MilvusClient
client = MilvusClient(
uri="http://localhost:19530",
)
index_params = client.prepare_index_params() # Prepare an empty IndexParams object, without having to specify any index parameters
index_params.add_index(
field_name="category", # Name of the scalar field to be indexed
index_type="BITMAP", # Type of index to be created
index_name="category_bitmap_index" # Name of the index to be created
)
client.create_index(
collection_name="my_collection", # Specify the collection name
index_params=index_params
)
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.common.IndexParam;
import io.milvus.v2.service.index.request.CreateIndexReq;
import java.util.Collections;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("http://localhost:19530")
.build());
client.createIndex(CreateIndexReq.builder()
.collectionName("my_collection")
.indexParams(Collections.singletonList(IndexParam.builder()
.fieldName("category")
.indexType(IndexParam.IndexType.BITMAP)
.indexName("category_bitmap_index")
.build()))
.build());
import (
"context"
"log"
"github.com/milvus-io/milvus/client/v3/index"
"github.com/milvus-io/milvus/client/v3/milvusclient"
)
ctx := context.Background()
cli, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: "http://localhost:19530",
})
if err != nil {
log.Fatal("failed to connect to milvus server: ", err.Error())
}
_, err = cli.CreateIndex(ctx, milvusclient.NewCreateIndexOption("my_collection", "category", index.NewBitmapIndex()).WithIndexName("category_bitmap_index"))
if err != nil {
log.Fatal("failed to create index: ", err.Error())
}
use milvus::v2::prelude::*;
let config = ConnectConfig::new().uri("http://localhost:19530");
let client = ClientV2::new(&config).await?;
client
.create_index(
CreateIndexRequest::builder()
.collection_name("my_collection")
.index_param(
IndexParam::new()
.field_name("category")
.index_type(IndexType::Bitmap)
.index_name("category_bitmap_index"),
)
.build()?,
)
.await?;
#include <iostream>
#include "milvus/MilvusClientV2.h"
auto client = milvus::MilvusClientV2::Create();
auto status = client->Connect(milvus::ConnectParam("http://localhost:19530"));
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
status = client->CreateIndex(milvus::CreateIndexRequest().WithCollectionName("my_collection")
.AddIndex(milvus::IndexDesc("category", "category_bitmap_index", milvus::IndexType::BITMAP)));
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
import { MilvusClient } from "@zilliz/milvus2-sdk-node";
const client = new MilvusClient({ address: "http://localhost:19530" });
await client.createIndex({
collection_name: "my_collection",
field_name: "category",
index_type: "BITMAP",
index_name: "category_bitmap_index",
});
using Milvus.Client.V2;
using Milvus.Client.V2.Requests.Index;
using Milvus.Client.V2.Types;
var config = new ConnectConfig
{
Uri = "http://localhost:19530"
};
using var client = new MilvusClientV2(config);
await client.ConnectAsync();
// Prepare index building params
var indexParam = new IndexParam(
fieldName: "category",
indexType: IndexType.Bitmap,
indexName: "category_bitmap_index");
await client.CreateIndexAsync(new CreateIndexReq
{
CollectionName = "my_collection",
Indexes = [indexParam]
});
export CLUSTER_ENDPOINT="http://localhost:19530"
export TOKEN="root:Milvus"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/indexes/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--header "Request-Timeout: 10" \
-d '{
"collectionName": "my_collection",
"indexParams": [
{
"fieldName": "category",
"indexName": "category_bitmap_index",
"indexType": "BITMAP"
}
]
}'
# {
# "code": 0,
# "data": {}
# }
في هذا المثال، نقوم بإنشاء فهرس صور نقطية في الحقل category الخاص بمجموعة my_collection. تُستخدم طريقة add_index() لتحديد اسم الحقل ونوع الفهرس واسم الفهرس.
بمجرد إنشاء فهرس الصورة النقطية، يمكنك استخدام المعلمة filter في عمليات الاستعلام لإجراء تصفية قياسية استنادًا إلى الحقل المفهرس. يتيح لك ذلك تضييق نطاق نتائج البحث بكفاءة باستخدام فهرس الصورة النقطية. لمزيد من المعلومات، راجع شرح التصفية.
إزالة فهرس
استخدم الطريقة ` drop_index() ` لإزالة فهرس موجود من مجموعة.
في الإصدار 2.6.3 أو ما قبله، يجب تحرير المجموعة قبل حذف فهرس سكالي.
بدءًا من الإصدار 2.6.4 أو الأحدث، يمكنك حذف الفهرس القياسي مباشرةً بمجرد انتفاء الحاجة إليه — دون الحاجة إلى تحرير المجموعة أولاً.
client.drop_index(
collection_name="my_collection", # Name of the collection
index_name="category_bitmap_index" # Name of the index to drop
)
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.service.index.request.DropIndexReq;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("http://localhost:19530")
.build());
client.dropIndex(DropIndexReq.builder()
.collectionName("my_collection")
.indexName("category_bitmap_index")
.build());
import (
"context"
"log"
"github.com/milvus-io/milvus/client/v3/milvusclient"
)
ctx := context.Background()
cli, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: "http://localhost:19530",
})
if err != nil {
log.Fatal("failed to connect to milvus server: ", err.Error())
}
err = cli.DropIndex(ctx, milvusclient.NewDropIndexOption("my_collection", "category_bitmap_index"))
if err != nil {
log.Fatal("failed to drop index: ", err.Error())
}
use milvus::v2::prelude::*;
let config = ConnectConfig::new().uri("http://localhost:19530");
let client = ClientV2::new(&config).await?;
client
.drop_index(
DropIndexRequest::builder()
.collection_name("my_collection")
.index_name("category_bitmap_index")
.build()?,
)
.await?;
#include <iostream>
#include "milvus/MilvusClientV2.h"
auto client = milvus::MilvusClientV2::Create();
auto status = client->Connect(milvus::ConnectParam("http://localhost:19530"));
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
status = client->DropIndex(milvus::DropIndexRequest()
.WithCollectionName("my_collection")
.WithIndexName("category_bitmap_index"));
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
import { MilvusClient } from "@zilliz/milvus2-sdk-node";
const client = new MilvusClient({ address: "http://localhost:19530" });
await client.dropIndex({
collection_name: "my_collection",
index_name: "category_bitmap_index",
});
using Milvus.Client.V2.Requests.Index;
await client.DropIndexAsync(new DropIndexReq
{
CollectionName = "my_collection", // Name of the collection
IndexName = "category_bitmap_index" // Name of the index to drop
});
export CLUSTER_ENDPOINT="http://localhost:19530"
export TOKEN="root:Milvus"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/indexes/drop" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--header "Request-Timeout: 10" \
-d '{
"collectionName": "my_collection",
"indexName": "category_bitmap_index"
}'
# {
# "code": 0,
# "data": {}
# }
القيود
يتم دعم الفهارس النقطية فقط للحقول العددية التي ليست مفاتيح أساسية.
يجب أن يكون نوع بيانات الحقل أحد الأنواع التالية:
BOOL،INT8،INT16،INT32،INT64،VARCHARARRAY(يجب أن تكون العناصر أحد الأنواع التالية:BOOL،INT8،INT16،INT32،INT64،VARCHAR)
لا تدعم فهارس الصور النقطية أنواع البيانات التالية:
FLOAT،DOUBLE: أنواع النقاط العائمة غير متوافقة مع الطبيعة الثنائية لفهرس الصور النقطية.JSON: تتميز أنواع بيانات JSON ببنية معقدة لا يمكن تمثيلها بكفاءة باستخدام الفهارس النقطية.
فهرس الصور النقطية غير مناسب للحقول ذات الكاردينالية العالية (أي الحقول التي تحتوي على عدد كبير من القيم المتميزة).
كإرشاد عام، تكون الفهارس النقطية أكثر فعالية عندما يكون عدد القيم في الحقل أقل من 500.
عندما يزيد عدد القيم عن هذا الحد، تتضاءل مزايا أداء الفهارس النقطية، وتصبح تكلفة التخزين كبيرة.
بالنسبة للحقول ذات الكاردينالية العالية، ضع في اعتبارك استخدام تقنيات فهرسة بديلة مثل الفهارس المقلوبة، اعتمادًا على حالة الاستخدام المحددة ومتطلبات الاستعلام.