04 أغسطس 2025·6 دقيقة قراءة

البحث في PostgreSQL في كل مكان: البحث النصي الكامل، فهرس trigram، والفهارس الجزئية

تعلّم كيف تصمّم "بحث في كل مكان" في PostgreSQL للشاشات الداخلية عن طريق اختيار البحث النصي الكامل، فهارس trigram، والفهارس الجزئية للحصول على نتائج سريعة.

البحث في PostgreSQL في كل مكان: البحث النصي الكامل، فهرس trigram، والفهارس الجزئية

ماذا يعني "البحث في كل مكان" فعليًا للأدوات الداخلية

في شاشة داخلية، "البحث في كل مكان" عادةً يعني: "ساعدني في العثور على السجل الذي أفكر فيه، بسرعة، حتى لو لم أتذكّره تمامًا." الناس لا يتصفحون؛ يريدون القفز مباشرة إلى عميل، تذكرة، فاتورة، أو جهاز واحد.

لهذا السبب يبدو البحث البطيء أسوأ من تحميل صفحة بطيئة. تحميل الصفحة يحدث مرة واحدة؛ البحث يحدث مرات كثيرة على التوالي، غالبًا أثناء مكالمة أو أثناء فرز أولي. إذا استغرقت النتائج 2–3 ثوانٍ، يغيّر المستخدمون الاستعلام، يمسحون، يجربون مصطلحًا آخر، وفي النهاية تزيد التحميلات والإحباط.

من صندوق بحث واحد، يتوقع المستخدمون مجموعة من السلوكيات: مطابقات جزئية ("alex" يجد "Alexander"), تسامح مع أخطاء صغيرة ("microsfot" لا يزال يجد "Microsoft"), ترتيب "أفضل نتيجة" معقول (المعرّفات أو الإيميلات الدقيقة تظهر في الأعلى)، تحيّز طفيف للحداثة، وعوامل تصفية تُطبّق افتراضيًا (التذاكر المفتوحة، العملاء النشطون).

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

لذا لا تبدأ بالفهارس. ابدأ بكتابة النوايا القليلة التي يحتاجها المستخدمون بالفعل، وافصل حقول الهوية (المعرّفات، الإيميلات) عن الحقول الغامضة (الأسماء، العناوين) والنصوص الطويلة (الملاحظات).

ابدأ بتسمية البيانات وسلوكيات البحث

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

الأدوات الداخلية تدمج معرفات "صارمة" (رقم الطلب، رقم التذكرة، رمز الفاتورة) مع نص "لين" (اسم العميل، البريد الإلكتروني، الملاحظات، الوسوم). تلك المجموعات تتصرف بشكل مختلف في PostgreSQL، فإذا عاملتها بنفس الطريقة فستحصل بسرعة على استعلامات بطيئة.

بعد ذلك، فرّق السلوكيات:

  • مطابقة دقيقة: شخص يبحث TCK-104883 يتوقع نتيجة واحدة دقيقة.
  • مطابقة غامضة: شخص يكتب john smth يريد مطابقة متسامحة عبر الأسماء (وربما الإيميلات) ويستعرض قائمة قصيرة.
  • بحث مدفوع بعوامل التصفية: شخص يختار "الحالة = مفتوحة" و"معين لي" يكون أساسًا في طور التصفية؛ صندوق النص ثانوي.

قرر مبكرًا هل يجب ترتيب النتائج (الأفضل أولًا) أم الاكتفاء بالفلترة. الترتيب مهم للملاحظات والنصوص الطويلة. بالنسبة للمعرّفات والإيميلات، الترتيب غالبًا يبدو عشوائيًا ويضيف تكلفة.

قائمة تحقق قصيرة عادة كافية:

  • أي الحقول تُبحث يوميًا؟
  • أي المدخلات دقيقة (معرّفات، أكواد)، غامضة (أسماء)، أو نص طويل (ملاحظات)؟
  • أي عوامل التصفية تطبق تقريبًا على كل بحث؟
  • هل تحتاج ترتيب "أفضل تطابق" أم أي تطابق مقبول؟
  • كم سيكبر الجدول: آلاف، مئات الآلاف، أم ملايين؟

إذا سمّيت تلك القرارات مقدمًا، تختفي تخمينات اختيار الفهرس لاحقًا.

الأساس: المطابقات الدقيقة ولماذا ILIKE غالبًا ما يضر

قم بثبيت المكاسب السهلة أولًا. للعديد من الشاشات الداخلية، فهرس B-tree العادي يعطي نتائج فورية للمطابقات الدقيقة مثل المعرّفات، أرقام الطلب، الإيميلات، والمرجع الخارجي.

إذا ألصق الناس قيمة دقيقة، تأكد أن استعلامك دقيق فعلًا. WHERE id = ... أو WHERE email = ... يمكن أن يكون سريعًا جدًا مع فهرس عادي. فهرس فريد على البريد الإلكتروني غالبًا ما يدفع الفائدة مرتين: السرعة وجودة البيانات.

المشكلة تبدأ عندما يتحول "البحث في كل مكان" بهدوء إلى ILIKE. استعلام مثل name ILIKE '%ann%' يحتوي على وائلدر بادئة، لذا لا يستطيع PostgreSQL استخدام فهرس B-tree عادي. ينتهي به الأمر بفحص الكثير من الصفوف، ويبطأ بشكل متوقع مع نمو الجدول.

يمكن أن يعمل بحث البادئة، لكن فقط عندما يكون النمط مثبتًا في البداية: name ILIKE 'ann%'. حتى عندها، التفاصيل مهمة (الترتيب اللغوي، التعامل مع الحالة، وما إذا كنت فهرست نفس التعبير الذي تستعلمه). إذا كانت واجهتك تنتظر سلوكًا غير حساس لحالة الأحرف، نهج شائع هو الاستعلام lower(name) وإنشاء فهرس مطابق على lower(name).

كما يساعد الاتفاق على ما يعنيه "سريع":

  • نحو 200 مللي ثانية أو أقل لعمل قاعدة البيانات على ذاكرة مخبأة دافئة
  • أقل من ثانية واحدة نهاية إلى نهاية بما في ذلك الشبكة والعرض
  • عدم ظهور حالة تحميل مرئية للبحثات الشائعة

مع أهداف كهذه، يصبح أسهل تحديد ما إذا كنت تستطيع الالتزام بالمطابقات الدقيقة والبادئة، أو حان وقت البحث النصي الكامل أو فهارس trigram.

متى يكون البحث النصي الكامل هو الأداة المناسبة

يكون البحث النصي الكامل الأنسب عندما يكتب الناس لغة طبيعية ويتوقعون أن يجد النظام العناصر الصحيحة، وليس مجرد مطابقات دقيقة. فكر في رسائل التذاكر، ملاحظات داخلية، أوصاف طويلة، مقالات قاعدة المعرفة، وسجلات المكالمات.

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

على مستوى عالٍ، للبحث النصي ثلاث مكونات متحركة:

  • tsvector (النص القابل للبحث، مخزنًا أو مولدًا)
  • tsquery (ما كتبه المستخدم، محوّلًا إلى استعلام)
  • إعداد اللغة (كيف تُطبّع الكلمات)

إعداد اللغة هو حيث يظهر السلوك للمستخدم. PostgreSQL يزيل كلمات التوقف الشائعة (مثل "the" أو "and") ويطبق التجذير، لذا "pay"، "paid"، و"payment" قد تتطابق. هذا مفيد للملاحظات والرسائل، لكنه قد يفاجئ عندما يبحث المستخدم عن كلمة قصيرة شائعة ولا يجد شيئًا.

المرادفات نقطة قرار أخرى. تساعد إذا كانت شركتك تستخدم كلمات مختلفة لنفس الشيء (مثل "refund" مقابل "chargeback"), لكنها تحتاج عناية مع مرور الوقت. اجعل قائمة المرادفات قصيرة ومبنية على ما يكتبه الدعم أو العمليات فعليًا.

مثال عملي: البحث عن "can't login after reset" يجب أن يستدعي تذاكر تقول "cannot log in after password reset" حتى لو اختلفت الصياغة. هذا السلوك في العثور على ذي صلة هو ما بُني له البحث النصي الكامل، وغالبًا ما يكون خيارًا أفضل من محاولة جعل ILIKE يعمل كمحرّك بحث.

متى تتفوّق فهارس trigram

اضبط نموذج بياناتك
فرّق حقول الهوية عن الحقول الغامضة مبكرًا ليبقى تطبيقك سريعًا مع نمو البيانات.
نمذجة البيانات

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

الـ trigram هو قطعة من 3 أحرف من النص. PostgreSQL يقارن سلسلتين بعدد trigram المشتركة بينهما. لهذا يمكنه مطابقة "Jon Smth" مع "John Smith"، أو "ACM" مع "ACME"، ويمكنه العثور على نتائج عندما يكون الاستعلام في منتصف كلمة.

غالبًا ما يكون هذا أسرع طريق لصندوق "البحث في كل مكان" المتسامح عندما تكون المهمة "اعثر لي على الصف الصحيح" وليس "ابحث عن مستندات حول موضوع".

أين يتفوق على البحث النصي الكامل

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

حافظ على تكلفة الكتابة معقولة

فهارس trigram أكبر وتضيف عبئًا على عمليات الكتابة، فكن انتقائيًا. قم بفهرسة الأعمدة التي يستخدمها الناس فعليًا:

  • الاسم، الإيميل، الشركة، اسم المستخدم
  • المعرفات القصيرة (SKU، رمز، مرجع)
  • حقل عنوان موجز (ليس حقل ملاحظات كبير)

إذا استطعت تسمية الحقول التي يكتبها فريقك في صندوق البحث، فعادةً ما يمكنك إبقاء فهرسة trigram صغيرة وسريعة.

الفهارس الجزئية للعوامل التي يستخدمها الناس فعليًا

اجعل البحث متوقعًا
استخدم منطق سحب وإفلات للحفاظ على سلوك البحث ثابتًا عبر الشاشات.
بناء المنطق

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

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

أهداف الفهرس الجزئي الشائعة تشمل الصفوف النشطة (status = 'active'), الحذف المنطقي (deleted_at IS NULL), تقييد المستأجر، ونوافذ "حديثة" (مثلاً آخر 90 يومًا).

المهم هو مطابقة واجهتك. إذا كانت الشاشة دائمًا تخفي الصفوف المحذوفة، يجب أن تتضمن استعلاماتك دائمًا deleted_at IS NULL، ويجب أن يستخدم الفهرس الجزئي نفس الشرط. الاختلافات الصغيرة، مثل استخدام is_deleted = false في مكان وdeleted_at IS NULL في آخر، قد تمنع المخطط من استخدام الفهرس.

الفهارس الجزئية تعمل أيضًا جنبًا إلى جنب مع البحث النصي وفهارس trigram. على سبيل المثال، فهرسة البحث النصي فقط للصفوف غير المحذوفة تُبقي حجم الفهرس تحت السيطرة.

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

مزج النهج دون تحويل البحث إلى لغز

معظم الفرق تنتهي بخلط الأساليب لأن صندوق بحث واحد يجب أن يتعامل مع نوايا مختلفة. الهدف هو جعل ترتيب العمليات واضحًا حتى تبدو النتائج متوقعة.

ترتيب أولوية بسيط يساعد، سواء نفّذته كاستعلامات منفصلة أو كاستعلام واحد مع منطق CASE واضح.

سلم أولوية متوقع

ابدأ صارمًا، ثم تدرّج إلى الغموض فقط عند الحاجة:

  • المطابقة الدقيقة أولًا (المعرّفات، الإيميل، رقم التذكرة، SKU) باستخدام فهارس B-tree
  • مطابقة البادئة بعد ذلك حيث يتناسب
  • مطابقة trigram بعدها للأخطاء والشظايا في الأسماء والعناوين
  • البحث النصي الكامل أخيرًا للنصوص الطويلة والوصفية

عندما تلتزم بنفس السلم، يتعلم المستخدمون ماذا يعني الصندوق. يتوقفون عن الاعتقاد بأن النظام معطل عندما يجد "12345" تذكرة فورًا بينما "refund policy" يبحث في نص أطول.

صفِّ أولًا، ثم كن غامضًا

البحث الغامض يصبح مكلفًا عندما يضطر للنظر في الجدول بأكمله. قِص مجموعة المرشّحين بعوامل التصفية التي يستخدمها الناس غالبًا (الحالة، الفريق المعين، نطاق التاريخ، الحساب)، ثم شغّل trigram أو البحث النصي على الباقي. حتى فهرس trigram السريع قد يبدو بطيئًا إذا طُلب منه تقييم ملايين الصفوف.

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

خطوة بخطوة: اختر نهجًا ونفّذه بأمان

تجنّب دين تقنية البحث
تجنّب دين التقنيات بالوصول إلى شفرة مصدر جاهزة للإنتاج أثناء تغيّر متطلبات البحث.
توليد الكود

صندوق "البحث في كل مكان" السريع هو مجموعة قرارات صغيرة. اكتبها أولًا، ثم يصبح عمل قاعدة البيانات أبسط.

  1. حدد المدخلات. هل هو صندوق واحد فقط، أم صندوق واحد مع عوامل تصفية (حالة، مالك، نطاق تاريخ)؟
  2. اختر نوع المطابقة لكل حقل. المعرفات والأكواد تحتاج مطابقة دقيقة. الأسماء والإيميلات غالبًا تحتاج بادئة أو مطابقة غامضة. الملاحظات الطويلة والوصف أفضل مع البحث النصي.
  3. أضف الفهارس الصحيحة وتأكد من استخدامها. أنشئ الفهرس، ثم افحص الاستعلام الحقيقي باستخدام EXPLAIN (ANALYZE, BUFFERS).
  4. أضف ترتيبًا أو فرزًا يطابق النية. إذا كتب المستخدم "invoice 1042" يجب أن تطفو المطابقات الدقيقة للأعلى. إذا كتب اسمًا مكتوبًا خطأً، يجب أن يفوز الترتيب بالتشابه.
  5. اختبر باستعلامات حقيقية. جرّب أخطاء مطبعية، مصطلحات قصيرة جدًا (مثل "al"), نصوص طويلة ملصوقة، إدخال فارغ، ووضع "فقط عوامل التصفية".

للنشر الآمن، غيّر شيئًا واحدًا في كل مرة واجعل التراجع سهلًا. للفهارس الجديدة على الجداول الكبيرة، فضّل CREATE INDEX CONCURRENTLY حتى لا تمنع الكتابات. إن أمكن، أطلق خلف ميزة قابلة للتفعيل وقارن زمن الاستجابة قبل وبعد.

نمط عملي لـ"البحث في PostgreSQL في كل مكان": المطابقة الدقيقة أولًا (سريعة ودقيقة)، مطابقة trigram للحقول "البشرية" حيث يخطئ الناس، والبحث النصي للمحتوى الطويل الذي يستفيد من الترتيب.

مثال واقعي: صندوق بحث واحد في لوحة دعم

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

الفوز الأول هو جعل النية مرئية بدون إضافة احتكاك. إذا بدا الاستعلام كإيميل أو رقم هاتف، عامله كبحث عن عميل. إذا بدا كرقم تذكرة (مثلاً "TKT-10482"), وجّهه فورًا للتذاكر. كل شيء آخر يعود لبحث نصي عبر موضوع التذكرة والملاحظات.

للبحث عن العملاء، عادةً ما تبدو فهارس trigram الأفضل. الأسماء والشركات فوضوية، والناس يكتبون شظايا. فهرس trigram يجعل عمليات مثل "jon smi" أو "acm" سريعة ومتسامحة.

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

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

الاستعلامات القصيرة جدًا تستحق قواعد، وإلا تؤدي القاعدة لعمل باهظ مقابل ضوضاء قليلة:

  • حرفان أو أقل: اعرض التذاكر المفتوحة الحديثة والعملاء المحدثين مؤخرًا
  • 3+ أحرف: شغّل trigram لحقول العملاء والبحث النصي لمحتوى التذاكر
  • لا نية واضحة: اعرض قائمة مختلطة، لكن حد كل مجموعة (مثلاً 10 عملاء و10 تذاكر)

أخطاء شائعة تبطئ البحث أو تربكه

صفِّ أولًا ثم كن غامضًا
أضف عوامل التصفية الافتراضية مثل الحالة ومساحة العمل أولًا ليبقى البحث الغامض رخيصًا.
أضف عوامل التصفية

معظم أخطاء "لماذا البحث بطيء؟" من صنعنا نحن. الهدف ليس فهرسة كل شيء، بل فهرسة ما يفعله الناس فعليًا.

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

خطأ آخر هو استخدام البحث النصي الكامل عندما ما تحتاجه فعليًا هو بحث متسامح مع الأخطاء على الأسماء أو الإيميلات. البحث النصي رائع للوثائق والوصف. إنه ليس حلًا سحريًا لـ "Jon" مقابل "John" أو "gmail.con" مقابل "gmail.com". هذا عادة مجال trigram.

العوامل يمكن أن تكسر الخطة بصمت أيضًا. إذا حدثت معظم عمليات البحث مع فلتر ثابت (مثل status = 'open' أو org_id = 42), فالفهرس الأفضل قد يكون فهرسًا جزئيًا يطابق ذلك الشرط. إذا نسيت ذلك، قد يفحص PostgreSQL عددًا أكبر من الصفوف مما تتوقع.

بعض الأخطاء تتكرر:

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

مثال: شاشة دعم تبحث بالتوازي في موضوع التذكرة، اسم العميل، ورقم التذكرة، ثم ترتب بحسب أحدث نشاط. إذا لم يكن latest_activity_at مفهرسًا للمجموعة المصفاة (مثل التذاكر المفتوحة)، فإن ذلك الفرز قد يمحو السرعة التي كسبتها من فهرس البحث.

فحوصات سريعة قبل الإطلاق

أطلق لوحة إدارة حقيقية
أنشئ لوحة دعم أو عمليات تجد التذاكر والعملاء والملاحظات بسرعة.
بناء لوحة الإدارة

قبل إعلان ميزة "البحث في كل مكان" جاهزة، كن محددًا بالسلوك الذي تعد به.

  • هل الناس يحاولون العثور على سجل بمعرّف دقيق (رقم التذكرة، إيميل)؟
  • هل يتوقعون مطابقة غامضة للأخطاء؟
  • هل يريدون نتائج مرتبة من الملاحظات الأطول؟

إذا مزجت أوضاعًا، قرر أيها يفوز عند التعارض.

ثم حدد 2–3 حقول تقود معظم عمليات البحث. إذا كان 80% من البحث بالإيميل، الاسم، ورقم التذكرة، حسّن تلك أولًا وتعامل مع الباقي ثانويًا.

قائمة فحص قبل الإطلاق قصيرة:

  • أكد وضع المطابقة الرئيسي لكل حقل (مطابقة دقيقة، مطابقة غامضة، أم نص مرتب)
  • أدرج عوامل التصفية اليومية وتأكد أن الفهارس تطابق مزيجها
  • قرر كيف تتعامل مع الاستعلامات القصيرة والفارغة (مثلاً تطلب 2–3 أحرف للبحث الغامض؛ عرض "الأخيرة" عند الفراغ)
  • اجعل الترتيب مفسرًا: الأحدث، أفضل تطابق نصي، أو قاعدة مجمعة بسيطة

وأخيرًا، اختبر بحجم بيانات وتوقيت واقعيين، ليس فقط الصحة. استعلام يبدو فوريًا مع 1,000 صف قد يتباطأ عند مليون.

الخطوات التالية: حوّل الخطة إلى شاشة بحث داخلية سريعة

يبقى صندوق البحث سريعًا عندما يتفق الفريق على ماذا يجب أن يفعل. اكتب القواعد بلغة بسيطة: ماذا يعني "مطابق" (دقيق، بادئة، متسامح مع الأخطاء)، أي الحقول تُبحث، وكيف تغير الفلاتر مجموعة النتائج.

احتفظ بمجموعة اختبار صغيرة من عمليات البحث الحقيقية واجعلها مجموعة انحدار. 10–20 استعلامًا عادة كافٍ: بعض الأسماء الشائعة، بعض الإيميلات الجزئية، خطأ مطبعي، مقطع ملاحظة طويل، وحالة "لا نتائج". شغّلها قبل وبعد التغييرات حتى لا يكسر عمل الأداء صلة النتائج بصمت.

إذا كنت تبني أدوات داخلية باستخدام AppMaster (appmaster.io), فمن المفيد تعريف قواعد البحث هذه جنبًا إلى جنب مع نموذج البيانات والمنطق التجاري، حتى لا ينحرف سلوك الواجهة وخيارات قاعدة البيانات عندما تتغير المتطلبات.

الأسئلة الشائعة

ماذا يعني "البحث في كل مكان" عادة في أداة داخلية؟

اعتبرها “العثور على السجل المقصود بسرعة” وليس التصفح. ابدأ بكتابة النوايا الحقيقية للمستخدمين (بحث بالمعرّف، بحث اسم/بريد مع أخطاء، أو بحث بالنص الطويل) والعوامل الافتراضية التي يستخدمونها غالبًا. هذه القرارات تُحدد أي استعلامات تنفّذ وأي فهارس تستحق التكلفة.

لماذا يجعل `ILIKE '%...%'` البحث بطيئًا؟

ILIKE '%term%' يحتوي على وائلدر بادئة، لذا عادةً لا يمكن لـ PostgreSQL استخدام فهرس B-tree عادي وينتهي به الأمر بفحص عدد كبير من الصفوف. قد يبدو جيدًا على جداول صغيرة، لكنه يبطئ كثيرًا مع نمو البيانات. إذا كنت تحتاج مطابقات فرعية أو تسامحًا مع الأخطاء، فخطط لاستخدام trigram أو full-text بدل الاعتماد على ILIKE فقط.

ما أسرع طريقة للتعامل مع عمليات البحث الدقيقة مثل المعرّفات أو الإيميلات؟

استخدم مقارنات دقيقة مثل WHERE id = $1 أو WHERE email = $1 وادعمها بفهرس B-tree (غالبًا فريد للإيميلات أو الرموز). عمليات البحث الدقيقة هي أرخص أنواع البحث وتجعل النتائج متوقعة. إذا ألصق المستخدم رقم تذكرة كاملًا أو بريدًا إلكترونيًا، وجّه الاستعلام لمسار المطابقة الدقيقة أولًا.

كيف أجري بحث بادئة غير حساس لحالة الأحرف دون كسر الفهارس؟

فضّل نمط بادئ مثل name ILIKE 'ann%' واجعله متناسقًا مع الفهرس الذي تنشئه. للسلوك غير الحساس لحالة الأحرف، يستعمل الكثيرون lower(name) وينشؤون فهرسًا على نفس التعبير حتى يتمكن المخطط من استخدامه. إذا لم تستطع تثبيت النمط عند البداية، فإن بحث البادئة وحده لن يكفي.

متى أستخدم فهارس trigram لصندوق البحث؟

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

متى يكون البحث النصي الكامل في PostgreSQL الخيار الأفضل؟

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

كيف تساعد الفهارس الجزئية شاشات "البحث في كل مكان"؟

أضف فهارس جزئية عندما تتضمن معظم عمليات البحث نفس عوامل التصفية مثل deleted_at IS NULL، status = 'open' أو قيد مساحة عمل/مستأجر. لأن الفهرس يغطي الجزء المشترك فقط، يبقى أصغر وغالبًا أسرع في الأحمال الحقيقية. تأكد أن استعلاماتك تستخدم نفس شرط الفلترة بالضبط، وإلا قد يتجاهل PostgreSQL الفهرس.

كيف أدمج البحث الدقيق وtrigram والنصي دون أن أربك المستخدمين؟

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

ماذا أفعل بعمليات البحث ذات حرفين أو أقل أو المدخل الفارغ؟

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

كيف أتحقق من الأداء وأطلق تغييرات البحث بأمان؟

إنشئ الفهرس ثم تحقق من الاستعلام الحقيقي باستخدام EXPLAIN (ANALYZE, BUFFERS) على أحجام بيانات واقعية، لا مجرد مجموعة تطوير صغيرة. نزّل التغييرات واحدة تلو الأخرى واجعل التراجع سهلاً؛ على الجداول الكبيرة، أنشئ الفهارس باستخدام CREATE INDEX CONCURRENTLY لتجنب حظر الكتابة. إذا بنيت الشاشة في AppMaster (appmaster.io)، عرّف قواعد البحث مع نموذج البيانات والمنطق التجاري حتى لا ينحرف سلوك الواجهة عند تغير المتطلبات.

من السهل أن تبدأ
أنشئ شيئًا رائعًا

تجربة مع AppMaster مع خطة مجانية.
عندما تكون جاهزًا ، يمكنك اختيار الاشتراك المناسب.

البدء
البحث في PostgreSQL في كل مكان: البحث النصي الكامل، فهرس trigram، والفهارس الجزئية | AppMaster