1. مفهوم الفهرس وتطبيقاته

1.1 ما هو الفهرس

الفهرس هو هيكل بيانات يُستخدم في نظام إدارة قاعدة البيانات لتسريع عمليات استرجاع البيانات. يمكن اعتباره "دليلاً" في قاعدة البيانات، حيث يُمكن بسرعة تحديد موقع البيانات في جدول البيانات، مما يمنع البحث الكامل في الجدول ويحسن بشكل كبير كفاءة الاستعلام. في التطبيقات العملية، يمكن أن يعزز الاستخدام الصحيح للفهارس أداء قاعدة البيانات بشكل كبير.

1.2 أنواع الفهارس

هناك أنواع مختلفة من الفهارس، كلٌّ منها له تصميمه وتحسينه الخاص لسيناريوهات تطبيق مختلفة:

  • الفهرس ذو الحقل الواحد: وهو فهرس يتضمن حقلًا واحدًا فقط، وهو مناسب للسيناريوهات التي تعتمد على شرط واحد للاستعلامات السريعة.
  • الفهرس المركب: وهو فهرس يتضمن عدة حقول، مما يوفر الأمثلية للاستعلامات التي تحتوي على تلك الحقول.
  • الفهرس الفريد: يضمن فرادة حقول الفهرس، ممنعًا وجود قيم مكررة. يمكن أن تكون الفهارس الفريدة ذات حقل واحد أو مركبة.

2. تعريف الفهرس

2.1 تعريف فهرس الحقل

يشمل إنشاء فهرس ذو حقل واحد تأسيس فهرس على عمود محدد في جدول البيانات، ويمكن تحقيق ذلك باستخدام طريقة Fields. وفيما يلي مثال يوضح كيفية إنشاء فهرس على حقل "الهاتف" في كيان "المستخدم".

func (User) Fields() []ent.Field {
    return []ent.Field{
        field.String("phone"),
    }
}
func (User) Indexes() []ent.Index {
    // إنشاء فهرس ذو حقل واحد
    return []ent.Index{
        index.Fields("phone"),
    }
}

في هذا المقطع البرمجي، تم تفهيم حقل "الهاتف". يسمح هذا للنظام باستخدام الفهرس لعمليات البحث الأسرع عند الاستعلام عن حقل "الهاتف".

2.2 تعريف الفهرس الفريد

يضمن الفهرس الفريد فرادة البيانات على الأعمدة المفهرسة. يمكن إنشاؤه بإضافة طريقة Unique إلى الحقل. توضح الأمثلة التالية إنشاء فهارس فريدة لحقول واحدة ومتعددة.

إنشاء فهرس فريد لحقل واحد:

func (User) Fields() []ent.Field {
    return []ent.Field{
        field.String("email").Unique(),
    }
}

في هذا المثال، يتم تحديد حقل "البريد الإلكتروني" على أنه فريد، مما يضمن أن بريد كل مستخدم فريد في قاعدة البيانات.

إنشاء فهرس فريد لمجموعة من حقول:

func (User) Indexes() []ent.Index {
    return []ent.Index{
        // إنشاء فهرس فريد لعدة حقول
        index.Fields("first_name", "last_name").Unique(),
    }
}

يعرف هذا الكود فهرس فريد مركب لتركيبة من حقول "الاسم الأول" و "الاسم الأخير"، مما يمنع حدوث سجلات تحتوي على القيم نفسها في كلتا الحقلين.

2.3 تعريف الفهرس المركب

عندما تتضمن شروط الاستعلام عدة حقول، يمكن أن يكون لفهرس مركب دورًا. يخزن الفهرس المركب البيانات في الترتيب المعرف في الفهرس. يؤثر ترتيب الفهرس بشكل كبير على أداء الاستعلام، لذا عند تعريف فهرس مركب، يجب تحديد ترتيب الحقول بناءً على نمط الاستعلام.

فيما يلي مثال على إنشاء فهرس مركب:

func (User) Indexes() []ent.Index {
    return []ent.Index{
        // إنشاء فهرس مركب يتضمن عدة حقول
        index.Fields("country", "city"),
    }
}

في هذا المثال، يتم إنشاء فهرس مركب على الحقول "البلد" و "المدينة". وهذا يعني أنه عند تنفيذ عمليات الاستعلام المتضمنة لهاتين الحقلين، يمكن لقاعدة البيانات تحديد المواقع بسرعة التي تستجيب للشروط.

إن الفهرس المركب لا يسرع فقط أداء الاستعلام ولكنه يدعم أيضًا عمليات الفرز المعتمدة على الفهرس، وبذلك يوفر أداء استرجاع البيانات أكثر كفاءة. عند تصميم فهرس مركب، فمن الشائع وضع الحقول ذات الانتقائية الأعلى في الجزء الأمامي من الفهرس، بحيث يمكن لمحسن قاعدة البيانات استخدام الفهرس بشكل أفضل.

3. فهم مؤشرات الحافة

في إطار ent، تُعد مؤشرات الحافة وسيلة لتعريف المؤشرات من خلال الحواف (العلاقات). يُستخدم هذا الآلية عادةً لضمان فريدية الحقول تحت العلاقات المحددة. على سبيل المثال، إذا كان نموذج قاعدة البيانات يتضمن مدنًا وشوارعًا، ويجب أن يكون لكل اسم شارع تحت مدينة فريد، يمكن استخدام مؤشرات الحافة لتحقيق ذلك.

// الملف ent/schema/street.go يُحدد مخطط كيان الشارع.
نوع Street struct {
    ent.Schema
}

نوع (Street) حقول() []ent.Field {
    // تعريف الحقول
    return []ent.Field{
        field.String("name"),
    }
}

نوع (Street) حواف() []ent.Edge {
    // تحديد العلاقة بين مدينة وشارع، حيث ينتمي الشارع إلى مدينة.
    return []ent.Edge{
        edge.From("city", City.Type).
            Ref("streets").
            Unique(),
    }
}

نوع (Street) مؤشرات() []ent.Index {
    // إنشاء مؤشر فريد عبر الحافة لضمان فريدية أسماء الشوارع داخل نفس المدينة.
    return []ent.Index{
        index.Fields("name").
            Edges("city").
            Unique(),
    }
}

في هذا المثال، نقوم بإنشاء كيان "Street" وربطه بكيان "City". عن طريق تعريف مؤشر الحافة في طريقة "Indexes" لكيان "Street"، نضمن فريدية اسم كل شارع تحت مدينة.

الفصل 5: خيارات المؤشرات المتقدمة

5.1 مؤشرات نصية كاملة ومؤشرات هاش

مؤشر النص الكامل ومؤشر الهاش هما نوعان فريديان من مؤشرات في MySQL وPostgreSQL، ويُستخدمان لسيناريوهات تحسين الاستعلام المختلفة.

يُستخدم مؤشر النص الكامل عادةً للبحث في البيانات النصية، خاصةً عندما تحتاج إلى إجراء بحوث معقدة، مثل البحوث عن تطابق الكلمات. تدعم قواعد بيانات كلا MySQL وPostgreSQL مؤشر النص الكامل. على سبيل المثال، في MySQL، يمكنك تعريف مؤشر نص كامل مثل هذا:

// الملف ent/schema/user.go يُحدد مخطط كيان المستخدم
نوع (User) مؤشرات() []ent.Index {
    // إنشاء مؤشر نصي كامل باستخدام الفئة FULLTEXT في MySQL
    return []ent.Index{
        index.Fields("description").
            Annotations(entsql.IndexTypes(map[string]string{
                dialect.MySQL: "FULLTEXT",
            })),
    }
}

مؤشر الهاش مناسب بشكل خاص للاستعلامات المتساوية ولا يدعم فرز واستعلامات المدى. في PostgreSQL، يمكنك استخدام مؤشر هاش مثل هذا:

نوع (User) مؤشرات() []ent.Index {
    // تعريف مؤشر من نوع HASH
    return []ent.Index{
        index.Fields("c4").
            Annotations(entsql.IndexType("HASH")),
    }
}

5.2 المؤشرات الجزئية وبادئات المؤشرات

المؤشر الجزئي هو نوع من المؤشر الذي يُؤشر فقط على الصفوف في جدول تلبي شروطًا محددة. في SQLite وPostgreSQL، يمكنك استخدام جملة WHERE لإنشاء مؤشرات جزئية.

على سبيل المثال، تعريف مؤشر جزئي في PostgreSQL:

نوع (User) مؤشرات() []ent.Index {
    // إنشاء مؤشر جزئي على حقل "nickname"، يحتوي فقط على الصفوف حيث "active" هو صحيح
    return []ent.Index{
        index.Fields("nickname").
            Annotations(
                entsql.IndexWhere("active"),
            ),
    }
}

مؤشر البادئة مفيد بشكل خاص لحقول النص، خاصةً في MySQL. يمكنه تقصير وقت إنشاء المؤشر، وتقليل المساحة التي يشغلها المؤشر، وكذلك توفير أداء جيد. كما هو موضح أدناه، يمكنك تعريف مؤشر ببادئة في MySQL:

نوع (User) مؤشرات() []ent.Index {
    // إنشاء مؤشر ببادئة
    return []ent.Index{
        index.Fields("description").
            Annotations(entsql.Prefix(128)),
    }
}

5.3 تعليقات المؤشرات والتخصيص

في ent، التعليقات هي ميزة تسمح للمطورين بتخصيص المؤشرات. يمكنك تحديد نوع المؤشر، وتعيين قواعد الفرز، والمزيد.

على سبيل المثال، يُظهر الكود التالي كيفية تحديد قواعد فرز الأعمدة في مؤشر:

نوع (User) مؤشرات() []ent.Index {
    return []ent.Index{
        // استخدام التعليقات لتحديد قواعد فرز الأعمدة في المؤشر
        index.Fields("c1", "c2", "c3").
            Annotations(entsql.DescColumns("c1", "c2")),
    }
}

باستخدام ميزة التعليقات، يمكن للمطورين تخصيص المؤشرات بشكل مرن لتحسين أداء وهيكل قاعدة البيانات.