أوراكل متعددة التداخل بين البيانات
سؤال
هل ستقوم Oracle بتسوية العبارات المتعددة بين الجمل إذا كانت تحتوي على بيانات متداخلة؟في تطبيقي، يمكن للمستخدمين إنشاء مصطلحات بحث ديناميكية، لذلك من الممكن أن تكون هناك بيانات متداخلة.هل ستقوم Oracle بتحسين SQL لي أم يجب علي حسابه قبل إنشاء SQL؟
أي.
حدد المعرف من xxtable حيث المعرف (بين 10 و 20) أو (بين 18 و 30)
هل سيتم تشغيله "كما هو" أو تحويله إلى:
حدد المعرف من xxtable حيث المعرف (بين 10 و 30)
شكرا على وقتك.
المحلول
وهذا يعتمد على الاستعلام عن كيفية محسن والتعامل معها. يمكنك اختبار في SQLPlus باستخدام autotrace والنظر في معلومات المسند (يتم ذلك على Oracle الإصدار 10.2.0.3):
SQL>set autot traceonly
SQL>
1 select l
2 from (SELECT l
3 FROM (SELECT LEVEL l
4 FROM dual CONNECT BY LEVEL < 20
5 )
6 )
7 where l between 5 and 10
8* or l between 7 and 15;
11 rows selected.
Elapsed: 00:00:00.21
Execution Plan
----------------------------------------------------------
Plan hash value: 2403765415
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 13 | 2 (0)| 00:00:01 |
|* 1 | VIEW | | 1 | 13 | 2 (0)| 00:00:01 |
|* 2 | CONNECT BY WITHOUT FILTERING| | | | | |
| 3 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("L">=5 AND "L"<=10 OR "L">=7 AND "L"<=15)
2 - filter(LEVEL<20)
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
0 consistent gets
0 physical reads
0 redo size
494 bytes sent via SQL*Net to client
403 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
11 rows processed
ولا إعادة كتابة قام به محسن في هذه الحالة على المعايير حيث، ولكن إذا كان لنا أن تغييره قليلا:
SQL>
1 select l
2 from (SELECT l
3 FROM (SELECT LEVEL l
4 FROM dual CONNECT BY LEVEL < 20
5 )
6 )
7 where l between 5 and 10
8* or l between 7 and 10;
6 rows selected.
Elapsed: 00:00:00.20
Execution Plan
----------------------------------------------------------
Plan hash value: 2403765415
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 13 | 2 (0)| 00:00:01 |
|* 1 | VIEW | | 1 | 13 | 2 (0)| 00:00:01 |
|* 2 | CONNECT BY WITHOUT FILTERING| | | | | |
| 3 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("L"<=10 AND ("L">=5 OR "L">=7))
2 - filter(LEVEL<20)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
0 consistent gets
0 physical reads
0 redo size
388 bytes sent via SQL*Net to client
392 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
6 rows processed
في هذا واحد ونحن نرى أن محسن لم تعترف أن كلا من حيث لديها معايير نفسها الحد الأعلى. لذلك يعتمد على الاستعلام عن كيفية محسن وإعادة كتابة عليه.
نصائح أخرى
من المفيد النظر إلى ما يحدث عندما نجري تجربة على جدول حقيقي يحتوي على فهرس.يحتوي هذا الجدول النموذجي على 69,241 صفًا وفهرسًا غير فريد في COL_3، مع إحصائيات.
حالة 1:هناك جملتان أساسيتان متداخلتان بين الجمل
SQL> set autotrace traceonly exp
SQL>
SQL> select * from big_table
2 where col_3 between 0.8 and 1
3 or col_3 between 0.9 and 1.1
4 /
Execution Plan
----------------------------------------------------------
Plan hash value: 3993303771
-------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 14737 | 805K| 176 (1)| 00:00:03 |
|* 1 | TABLE ACCESS FULL| BIG_TABLE | 14737 | 805K| 176 (1)| 00:00:03 |
-------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("COL_3"<=1.1 AND "COL_3">=0.9 OR "COL_3"<=1 AND
"COL_3">=0.8)
SQL>
النتيجة: يتم تجاهل الفهرس ويتبع ذلك فحص كامل للجدول
الحالة 2: تشترك عبارات BETWEEN في الحد الأعلى
SQL> select * from big_table
2 where col_3 between 0.8 and 1.1
3 or col_3 between 0.9 and 1.1
4 /
Execution Plan
----------------------------------------------------------
Plan hash value: 1461639892
-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 7924 | 433K| 114 (0)| 00:00:02 |
| 1 | TABLE ACCESS BY INDEX ROWID| BIG_TABLE | 7924 | 433K| 114 (0)| 00:00:02 |
|* 2 | INDEX RANGE SCAN | BIG3_IDX | 7924 | | 17 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("COL_3"<=1.1)
filter("COL_3">=0.8 OR "COL_3">=0.9)
SQL>
النتيجة: يتم استخدام الفهرس للحد الأعلى ويتم تجنب فحص الجدول بالكامل
الحالة 3: تشترك جمل BETWEEN في الحد الأدنى
SQL> select * from big_table
2 where col_3 between 0.8 and 1.1
3 or col_3 between 0.8 and 1.2
4 /
Execution Plan
----------------------------------------------------------
Plan hash value: 3993303771
-------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 15146 | 828K| 176 (1)| 00:00:03 |
|* 1 | TABLE ACCESS FULL| BIG_TABLE | 15146 | 828K| 176 (1)| 00:00:03 |
-------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(("COL_3"<=1.2 OR "COL_3"<=1.1) AND "COL_3">=0.8)
SQL>
النتيجة: يتم تجاهل الفهرس ويتبع ذلك فحص كامل للجدول
الحالة 4: يتم دمج النطاقين BETWEEN في جملة واحدة
SQL> select * from big_table
2 where col_3 between 0.8 and 1.1
3 /
Execution Plan
----------------------------------------------------------
Plan hash value: 1461639892
-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 7924 | 433K| 114 (0)| 00:00:02 |
| 1 | TABLE ACCESS BY INDEX ROWID| BIG_TABLE | 7924 | 433K| 114 (0)| 00:00:02 |
|* 2 | INDEX RANGE SCAN | BIG3_IDX | 7924 | | 17 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("COL_3">=0.8 AND "COL_3"<=1.1)
SQL>
النتيجة: يتم استخدام الفهرس لكل من الحدود العلوية والسفلية
لذا، باختصار، إذا تداخلت الجملتان BETWEEN وكان هناك فهرس في العمود، فقد يكون الأمر يستحق جهد دمجهما.