سؤال

لنفترض أن لدي جدول قاعدة بيانات يحتوي على حقلين، "foo" و"bar".ولا يعتبر أي منهما فريدًا من نوعه، ولكن يتم فهرسة كل منهما.ومع ذلك، بدلاً من فهرستها معًا، يكون لكل منها فهرس منفصل.

لنفترض الآن أنني أقوم بإجراء استعلام مثل SELECT * FROM sometable WHERE foo='hello' AND bar='world'; تحتوي طاولتي على عدد كبير من الصفوف التي يكون foo لها "مرحبًا" وعددًا صغيرًا من الصفوف التي يكون شريطها هو "العالم".

لذا فإن الشيء الأكثر فعالية الذي يجب أن يفعله خادم قاعدة البيانات ضمن الغطاء هو استخدام فهرس الشريط للعثور على جميع الحقول التي يكون فيها bar هو 'world'، ثم يُرجع فقط تلك الصفوف التي يكون foo لها 'hello'.هذا هو O(n) حيث n هو عدد الصفوف حيث يكون الشريط هو "العالم".

لكن أتصور أنه من الممكن أن تتم العملية بشكل عكسي، حيث يتم استخدام الفهرس fo والبحث في النتائج.هذا سوف يكون O(m) حيث m هو عدد الصفوف حيث foo هو "مرحبا".

فهل Oracle ذكية بما يكفي للبحث بكفاءة هنا؟ماذا عن قواعد البيانات الأخرى؟أم أن هناك طريقة ما يمكنني من خلالها إخبارها في استعلامي بالبحث بالترتيب الصحيح؟ربما عن طريق وضع bar='world' الأول في WHERE بند؟

هل كانت مفيدة؟

المحلول

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

علاوة على ذلك، يمكن لـ Oracle الجمع بين استخدام كلا الفهرسين بطريقتين - يمكنها تحويل فهارس btree إلى صور نقطية وتنفيذ صورة نقطية وعملية عليها، أو يمكنها إجراء وصلة تجزئة على الصف الذي تم إرجاعه بواسطة الفهرسين.

أحد الاعتبارات المهمة هنا قد يكون أي ارتباط بين القيم التي يتم الاستعلام عنها.إذا كان foo='hello' يمثل 80% من القيم في الجدول وbar='world' يمثل 10%، فسوف تقدر Oracle أن الاستعلام سيرجع 0.8*0.1= 8% من صفوف الجدول.ومع ذلك، قد لا يكون هذا صحيحًا - فقد يُرجع الاستعلام فعليًا 10% من rwos أو حتى 0% من الصفوف اعتمادًا على مدى ارتباط القيم.الآن، اعتمادًا على توزيع تلك الصفوف في جميع أنحاء الجدول، قد لا يكون من المفيد استخدام فهرس للعثور عليها.ربما لا تزال بحاجة إلى الوصول (على سبيل المثال) إلى 70% أو كتل الجدول لاسترداد الصفوف المطلوبة (Google لـ "عامل التجميع")، وفي هذه الحالة ستقوم Oracle بإجراء فحص كامل للجدول إذا حصلت على التقدير الصحيح.

في 11g، يمكنك جمع إحصائيات متعددة الأعمدة للمساعدة في هذا الموقف على ما أعتقد.في 9i و10g، يمكنك استخدام أخذ العينات الديناميكية للحصول على تقدير جيد جدًا لعدد الصفوف التي سيتم استرجاعها.

للحصول على خطة التنفيذ قم بما يلي:

explain plan for
SELECT *
FROM   sometable
WHERE  foo='hello' AND bar='world'
/
select * from table(dbms_xplan.display)
/

قارن ذلك بـ:

explain plan for
SELECT /*+ dynamic_sampling(4) */
       *
FROM   sometable
WHERE  foo='hello' AND bar='world'
/
select * from table(dbms_xplan.display)
/

نصائح أخرى

نعم، يمكنك تقديم "تلميحات" مع الاستعلام إلى Oracle.يتم إخفاء هذه التلميحات في شكل تعليقات ("/* HINT */") على قاعدة البيانات وهي خاصة بالمورد بشكل أساسي.لذلك لن يعمل تلميح واحد لقاعدة بيانات واحدة على قاعدة بيانات أخرى.

سأستخدم تلميحات الفهرس هنا، التلميح الأول للجدول الصغير.يرى هنا.

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

CREATE INDEX IX_BAR_AND_FOO on sometable(bar,foo);

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

إيلي،

في تعليق كتبت:

لسوء الحظ، لدي جدول يحتوي على الكثير من الأعمدة ولكل منها فهرس خاص بها.يمكن للمستخدمين الاستعلام عن أي مجموعة من الحقول، لذا لا يمكنني إنشاء فهارس بكفاءة في كل مجموعة حقول.ولكن إذا كان لدي حقلين فقط يحتاجان إلى فهارس، فأنا أتفق تمامًا مع اقتراحك باستخدام فهرسين.– إيلي كورترايت (29 سبتمبر الساعة 15:51)

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

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

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

فهل أوراكل ذكي بما يكفي للبحث بكفاءة هنا؟

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

أولاً، سأفترض أنك تتحدث عن فهارس b*-tree لطيفة وطبيعية ومعيارية.تختلف الإجابة عن فهارس الصور النقطية بشكل جذري.وهناك الكثير من الخيارات لأنواع مختلفة من الفهارس في Oracle والتي قد تغير الإجابة أو لا تغيرها.

كحد أدنى، إذا كان المحسن قادرًا على تحديد انتقائية حالة معينة، فسوف يستخدم فهرسًا أكثر انتقائية (أي.الفهرس الموجود على الشريط).ولكن إذا كانت لديك بيانات منحرفة (توجد قيم N في شريط العمود ولكن انتقائية أي قيمة معينة تكون أكبر أو أقل بكثير من 1/N من البيانات)، فسوف تحتاج إلى رسم بياني على العمود لتتمكن من معرفة ذلك المحسن أي القيم أكثر أو أقل احتمالا.وإذا كنت تستخدم متغيرات الربط (كما ينبغي لجميع مطوري OLTP الجيدين)، اعتمادًا على إصدار Oracle، فقد تكون لديك مشكلات تتعلق بإلقاء نظرة خاطفة على متغير الربط.

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

أنا متأكد من أنه يمكنك أيضًا جعل Oracle تعرض خطة استعلام حتى تتمكن من معرفة الفهرس الذي سيتم استخدامه أولاً.

يمكنك تقديم تلميحات حول الفهرس الذي سيتم استخدامه.لست على دراية بـ Oracle، ولكن في Mysql يمكنك استخدام USE|IGNORE|FORCE_INDEX (راجع هنا لمزيد من التفاصيل).للحصول على أفضل أداء، يجب عليك استخدام فهرس مدمج.

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

إنه أفضل من ذلك.

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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top