كيفية فرض أوراكل المكانية لتحديد خطة تنفيذ "القابلة للتنفيذ"

StackOverflow https://stackoverflow.com/questions/1044157

سؤال

وA (المكاني) الاستعلام في أوراكل 10g يحصل خطة تنفيذ مختلفة اعتمادا فقط على قيمة معلمة. وللأسف أوراكل لا يمكن تنفيذ واحدة من خطط على الإطلاق، وهو ما يعطي الخطأ. تغيير قيمة (أقل 282-284) أو مشغل (= إلى <) يعطي نتيجة لذلك. لماذا هي خطط مختلفة؟ لماذا يختار أوراكل خطة unexecutable؟ ما يجب القيام به لإجبار أوراكل لتحديد خطة التنفيذ للتنفيذ؟

والاستعلام:

  select nn.poi_id as id 
  from 
    poi p,
    (select pl.poi_id 
    from 
      poi_loc pl, 
      poi_loc pl2 
    where
     pl2.poi_id = 769
     and 
     pl.poi_id<>769
     and 
     sdo_nn(pl.wgs84, pl2.wgs84)='TRUE' 
  ) nn
  where
    cat_id = 282
    and
    p.id = nn.poi_id
       and 
     rownum<7;

وإعطاء الخطأ:

ORA-13249: SDO_NN cannot be evaluated without using index
ORA-06512: at "MDSYS.MD", line 1723
ORA-06512: at "MDSYS.MDERR", line 17
ORA-06512: at "MDSYS.PRVT_IDX", line 22

والخطة التي لا يتم تنفيذ:

| Id  | Operation                       | Name                    | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                |                         |     1 |   315 |     6   (0)| 00:00:01 |
|*  1 |  COUNT STOPKEY                  |                         |       |       |            |          |
|*  2 |   TABLE ACCESS BY INDEX ROWID   | POI_LOC                 |     1 |   153 |     2   (0)| 00:00:01 |
|   3 |    NESTED LOOPS                 |                         |     1 |   315 |     6   (0)| 00:00:01 |
|   4 |     NESTED LOOPS                |                         |     1 |   162 |     4   (0)| 00:00:01 |
|*  5 |      TABLE ACCESS BY INDEX ROWID| POI                     |     1 |     9 |     2   (0)| 00:00:01 |
|*  6 |       INDEX RANGE SCAN          | POI_CAT_ID_IDX          |     1 |       |     1   (0)| 00:00:01 |
|   7 |      TABLE ACCESS BY INDEX ROWID| POI_LOC                 |     1 |   153 |     2   (0)| 00:00:01 |
|*  8 |       INDEX RANGE SCAN          | POI_LOC_POI_ID_IDX      |     1 |       |     1   (0)| 00:00:01 |
|*  9 |     INDEX RANGE SCAN            | POI_LOC_POI_ID_IDX      |     1 |       |     1   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------------------

   1 - filter(ROWNUM<7)
   2 - filter("MDSYS"."SDO_NN"("PL"."WGS84","PL2"."WGS84")='TRUE')
   5 - filter("P"."ID"<>769)
   6 - access("CAT_ID"=282)
   8 - access("P"."ID"="PL"."POI_ID")
       filter("PL"."POI_ID"<>769)
   9 - access("PL2"."POI_ID"=769)

والخطة التي ينفذ ويعطي نتيجة

| Id  | Operation                      | Name                    | Rows  | Bytes | Cost (%CPU)| Time     |

----------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |                         |     6 |  1890 |   106   (1)| 00:00:02 |
|*  1 |  COUNT STOPKEY                 |                         |       |       |            |          |
|*  2 |   HASH JOIN                    |                         |     6 |  1890 |   106   (1)| 00:00:02 |
|*  3 |    TABLE ACCESS BY INDEX ROWID | POI                     |   573 |  5157 |    41   (0)| 00:00:01 |
|*  4 |     INDEX RANGE SCAN           | POI_CAT_ID_IDX          |   573 |       |     2   (0)| 00:00:01 |
|   5 |    NESTED LOOPS                |                         |   301 | 92106 |    65   (2)| 00:00:01 |
|   6 |     TABLE ACCESS BY INDEX ROWID| POI_LOC                 |     1 |   153 |     2   (0)| 00:00:01 |
|*  7 |      INDEX RANGE SCAN          | POI_LOC_POI_ID_IDX      |     1 |       |     1   (0)| 00:00:01 |
|*  8 |     TABLE ACCESS BY INDEX ROWID| POI_LOC                 |   302 | 46206 |    65   (2)| 00:00:01 |
|*  9 |      DOMAIN INDEX              | POI_LOC_SP_IDX          |       |       |            |          |
Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter(ROWNUM<7)
   2 - access("P"."ID"="PL"."POI_ID")
   3 - filter("P"."ID"<>769)
   4 - access("CAT_ID"=284)
   7 - access("PL2"."POI_ID"=769)
   8 - filter("PL"."POI_ID"<>769)
   9 - access("MDSYS"."SDO_NN"("PL"."WGS84","PL2"."WGS84")='TRUE')
هل كانت مفيدة؟

المحلول

وأنت فقط بحاجة لكتابة التلميح الطريقة الصحيحة:

select nn.poi_id as id 
  from 
    poi p,
    (select /*+ index (pl POI_LOC_SP_IDX) */ pl.poi_id 
    from 
      poi_loc pl, 
      poi_loc pl2 
    where
     pl2.poi_id = 769
     and 
     pl.poi_id<>769
     and 
     sdo_nn(pl.wgs84, pl2.wgs84)='TRUE' 
  ) nn
  where
    cat_id = 282
    and
    p.id = nn.poi_id
    and rownum<7;

وسبب الخطأ هو أن محسن يختار عدم استخدام مؤشر المكاني لأنه يعتقد أن الأخرى (غير المكانية) فهرسة المسندات أكثر انتقائية. توضيح: يجب أن يكون لديك مؤشر المكاني للاستعلامات المكانية للعمل، ولكن محسن قد تختار عدم استخدامه. هذا يعمل بشكل جيد لSDO_RELATE وSDO_ANYINTERACT المشغلين، ولكن ليس لSDO_NN.

نصائح أخرى

في أي حال، يجب أن تضيف مؤشر لWGS84.

إذا كان لديك أي فكرة عما يعني كل هذا، اطلب من DBA.

HTTP: // download-west.oracle.com/docs/cd/B19306_01/appdev.102/b14255/sdo_index_query.htm#i1000846 للحصول على بعض المعلومات.

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