كيف يمكنني اختيار تلميحات مختلفة للوصول المختلفة لجدول واحد في تلميح الاستعلام؟
-
22-09-2019 - |
سؤال
افترض أن لدي الاستعلام التالي:
select * from A, B, C, D
where A.x = B.x
and B.y = C.y
and A.z = D.z
لدي فهارس على AX و BX و BY و CY و DZ
لا يوجد فهرس على AZ
كيف يمكنني إعطاء تلميح لهذا الاستعلام لاستخدام تلميح فهرس على الفأس ولكن تلميح use_hash على AZ؟ يبدو أن التلميحات تأخذ اسم الجدول فقط ، وليس الانضمام المحدد ، لذلك عند استخدام جدول واحد مع توصيلات متعددة ، لا يمكنني سوى تحديد استراتيجية واحدة لها.
بديل ، لنفترض أنني أستخدم تلميحًا رائدًا أو مرتبة على الاستعلام أعلاه. كل من هذه التلميحات تأخذ فقط اسم الجدول أيضًا ، فكيف يمكنني التأكد من حدوث انضمام AX = BX قبل AZ = DZ واحد؟ أدرك في هذه الحالة أنه يمكنني القائمة D أولاً ، لكن تخيل D ينضم لاحقًا إلى E وأن De Join هو آخر مرة أريدها في الاستعلام بأكمله.
تكوين ثالث - لنفترض أنني أريد أن يكون انضمام الفأس هو الأول من الاستعلام بأكمله ، وأريد أن يكون انضمام AZ هو الأخير. كيف يمكنني استخدام تلميح للحصول على انضمام واحد من A ليتم ، يليه Join BC ، و Join AD LAST؟
المحلول
بادئ ذي بدء ، يجب أن يكون استخدام مثل هذه التلميحات هو الملاذ الأخير ، وليس طريقة عادية لكتابة الاستعلامات. في معظم الأوقات ، يجب عليك فقط التأكد من أن إحصائيات Optimiser محدثة وترك البنك المركزي العماني يعمل على العمل على المسار الأمثل لنفسه - هذا هو وظيفتها!
يمكن لتلميح الفهرس تحديد اسم الفهرس الذي تريد استخدامه مثل هذا:
SELECT /*+ INDEX (A, A_X_IDX) */ *
...
(على افتراض أن الفهرس على الفأس يسمى A_X_IDX).
لا يمكنك معرفة Oracle استخدام استخدام الفهرس على AX و استخدم انضمام التجزئة إلى الجدول A في نفس البيان ، وهذا لا معنى له. ومع ذلك ، يمكنك (إذا كان يجب عليك) تحديد مسار الوصول لكل جدول مثل:
SELECT /*+ INDEX (A, A_X_IDX) INDEX(B, B_Y_IDX) USE_HASH(C) */ *
ولكن للتكرار ، يجب أن يكون نادر للحاجة إلى القيام بذلك. استثمرت Oracle ملايين الدولارات ومانهور في تطوير CBO ، فلماذا إيقاف تشغيله بشكل فعال؟
نصائح أخرى
على SQL Server ، ستفعل تلميحًا مشتركًا مثل هذا
SELECT * FROM table1 t1
INNER hash join table2 t2 ON t1.id = t2.id
ويمكنك أيضًا توفير تلميح فهرس
select * from table1 t1
inner join table2 t2 with (index( bla)) on t1.id = t2.id
لا أعرف كيف يبدو بناء الجملة في Oracle ، راجع للشغل لماذا تستخدم صلات النمط القديم؟ هل ما زلت في 8i؟