Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

Thiếu STOPKEY trên mỗi phân vùng trong gói Oracle để phân trang theo chỉ mục cục bộ

Khi bạn sử dụng biến ràng buộc, Oracle buộc phải sử dụng cắt tỉa phân vùng động thay vì lược phân vùng tĩnh . Kết quả của việc này là tại thời điểm phân tích cú pháp, Oracle không biết phân vùng nào sẽ được truy cập, vì điều này thay đổi dựa trên các biến đầu vào của bạn.

Điều này có nghĩa là khi sử dụng các giá trị theo nghĩa đen (thay vì các biến liên kết), chúng tôi biết phân vùng nào sẽ được truy cập bởi chỉ mục cục bộ của bạn. Do đó count stopkey có thể được áp dụng cho đầu ra của chỉ mục trước khi chúng tôi cắt bớt các phân vùng.

Khi sử dụng các biến liên kết, partition range iterator phải tìm ra những phân vùng bạn đang truy cập. Sau đó, nó có một kiểm tra để đảm bảo rằng biến đầu tiên trong số các biến của bạn ở giữa các hoạt động thực sự có giá trị thấp hơn, sau đó là giá trị thứ hai (filter hoạt động trong kế hoạch thứ hai).

Điều này có thể dễ dàng được tái tạo, như trường hợp thử nghiệm sau đây cho thấy:

create table tab (
  x date,
  y integer,
  filler varchar2(100)
) partition by range(x) (
  partition p1 values less than (date'2013-01-01'),
  partition p2 values less than (date'2013-02-01'),
  partition p3 values less than (date'2013-03-01'),
  partition p4 values less than (date'2013-04-01'),
  partition p5 values less than (date'2013-05-01'),
  partition p6 values less than (date'2013-06-01')
);


insert into tab (x, y)
  select add_months(trunc(sysdate, 'y'), mod(rownum, 5)), rownum, dbms_random.string('x', 50)
  from   dual 
  connect by level <= 1000;

create index i on tab(x desc, y desc) local;

exec dbms_stats.gather_table_stats(user, 'tab', cascade => true);

explain plan for 
SELECT * FROM (
  SELECT rowid FROM tab
  where  x between date'2013-01-01' and date'2013-02-02'
  and    y between 50 and 100
  order  by x desc, y desc
)
where rownum <= 5;

SELECT * FROM table(dbms_xplan.display(null, null, 'BASIC +ROWS +PARTITION'));

--------------------------------------------------------------------                                                                                                                                                                                                                                         
| Id  | Operation                   | Name | Rows  | Pstart| Pstop |                                                                                                                                                                                                                                         
--------------------------------------------------------------------                                                                                                                                                                                                                                         
|   0 | SELECT STATEMENT            |      |     1 |       |       |                                                                                                                                                                                                                                         
|   1 |  COUNT STOPKEY              |      |       |       |       |                                                                                                                                                                                                                                         
|   2 |   VIEW                      |      |     1 |       |       |                                                                                                                                                                                                                                         
|   3 |    SORT ORDER BY STOPKEY    |      |     1 |       |       |                                                                                                                                                                                                                                         
|   4 |     PARTITION RANGE ITERATOR|      |     1 |     2 |     3 |                                                                                                                                                                                                                                         
|   5 |      COUNT STOPKEY          |      |       |       |       |                                                                                                                                                                                                                                         
|   6 |       INDEX RANGE SCAN      | I    |     1 |     2 |     3 |                                                                                                                                                                                                                                         
-------------------------------------------------------------------- 

explain plan for 
SELECT * FROM (
  SELECT rowid FROM tab
  where  x between to_date(:st, 'dd/mm/yyyy') and to_date(:en, 'dd/mm/yyyy')
  and    y between :a and :b
  order  by x desc, y desc
)
where rownum <= 5;

SELECT * FROM table(dbms_xplan.display(null, null, 'BASIC +ROWS +PARTITION'));

---------------------------------------------------------------------                                                                                                                                                                                                                                        
| Id  | Operation                    | Name | Rows  | Pstart| Pstop |                                                                                                                                                                                                                                        
---------------------------------------------------------------------                                                                                                                                                                                                                                        
|   0 | SELECT STATEMENT             |      |     1 |       |       |                                                                                                                                                                                                                                        
|   1 |  COUNT STOPKEY               |      |       |       |       |                                                                                                                                                                                                                                        
|   2 |   VIEW                       |      |     1 |       |       |                                                                                                                                                                                                                                        
|   3 |    SORT ORDER BY STOPKEY     |      |     1 |       |       |                                                                                                                                                                                                                                        
|   4 |     FILTER                   |      |       |       |       |                                                                                                                                                                                                                                        
|   5 |      PARTITION RANGE ITERATOR|      |     1 |   KEY |   KEY |                                                                                                                                                                                                                                        
|   6 |       INDEX RANGE SCAN       | I    |     1 |   KEY |   KEY |                                                                                                                                                                                                                                        
--------------------------------------------------------------------- 

Như trong ví dụ của bạn, truy vấn thứ hai chỉ có thể lọc các phân vùng thành một khóa key tại thời điểm phân tích cú pháp, thay vì phân vùng chính xác như trong ví dụ đầu tiên.

Đây là một trong những trường hợp hiếm hoi mà các giá trị theo nghĩa đen có thể cung cấp hiệu suất tốt hơn các biến ràng buộc. Bạn nên điều tra xem đây có phải là khả năng dành cho bạn không.

Cuối cùng, bạn nói rằng bạn muốn 20 hàng từ mỗi phân vùng. Truy vấn của bạn dưới dạng giá đỡ sẽ không thực hiện điều này, nó sẽ chỉ trả lại cho bạn 20 hàng đầu tiên theo thứ tự của bạn. Đối với 20 hàng / phân vùng, bạn cần làm như sau:

select rd from (
    select rowid rd, 
           row_number() over (partition by trx_id order by create_ts desc) rn
    from OUT_SMS     
    where  TRX_ID between ? and ?       
       and CREATE_TS between ? and ?
    order by CREATE_TS DESC, TRX_ID DESC
) where rn <= 20

CẬP NHẬT

Lý do bạn không nhận được count stopkey là làm với filter hoạt động trong dòng 4 của kế hoạch "xấu". Bạn có thể thấy điều này rõ ràng hơn nếu lặp lại ví dụ trên, nhưng không có phân vùng.

Điều này cung cấp cho bạn các kế hoạch sau:

----------------------------------------                                                                                                                                                                                                                                                                     
| Id  | Operation               | Name |                                                                                                                                                                                                                                                                     
----------------------------------------                                                                                                                                                                                                                                                                     
|   0 | SELECT STATEMENT        |      |                                                                                                                                                                                                                                                                     
|*  1 |  COUNT STOPKEY          |      |                                                                                                                                                                                                                                                                     
|   2 |   VIEW                  |      |                                                                                                                                                                                                                                                                     
|*  3 |    SORT ORDER BY STOPKEY|      |                                                                                                                                                                                                                                                                     
|*  4 |     TABLE ACCESS FULL   | TAB  |                                                                                                                                                                                                                                                                     
----------------------------------------                                                                                                                                                                                                                                                                     

Predicate Information (identified by operation id):                                                                                                                                                                                                                                                          
---------------------------------------------------                                                                                                                                                                                                                                                          

   1 - filter(ROWNUM<=5)                                                                                                                                                                                                                                                                                     
   3 - filter(ROWNUM<=5)                                                                                                                                                                                                                                                                                     
   4 - filter("X">=TO_DATE(' 2013-01-01 00:00:00', 'syyyy-mm-dd                                                                                                                                                                                                                                              
              hh24:mi:ss') AND "X"<=TO_DATE(' 2013-02-02 00:00:00', 'syyyy-mm-dd                                                                                                                                                                                                                             
              hh24:mi:ss') AND "Y">=50 AND "Y"<=100)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       

----------------------------------------                                                                                                                                                                                                                                                                     
| Id  | Operation               | Name |                                                                                                                                                                                                                                                                     
----------------------------------------                                                                                                                                                                                                                                                                     
|   0 | SELECT STATEMENT        |      |                                                                                                                                                                                                                                                                     
|*  1 |  COUNT STOPKEY          |      |                                                                                                                                                                                                                                                                     
|   2 |   VIEW                  |      |                                                                                                                                                                                                                                                                     
|*  3 |    SORT ORDER BY STOPKEY|      |                                                                                                                                                                                                                                                                     
|*  4 |     FILTER              |      |                                                                                                                                                                                                                                                                     
|*  5 |      TABLE ACCESS FULL  | TAB  |                                                                                                                                                                                                                                                                     
----------------------------------------                                                                                                                                                                                                                                                                     

Predicate Information (identified by operation id):                                                                                                                                                                                                                                                          
---------------------------------------------------                                                                                                                                                                                                                                                          

   1 - filter(ROWNUM<=5)                                                                                                                                                                                                                                                                                     
   3 - filter(ROWNUM<=5)                                                                                                                                                                                                                                                                                     
   4 - filter(TO_NUMBER(:A)<=TO_NUMBER(:B) AND                                                                                                                                                                                                                                                               
              TO_DATE(:ST,'dd/mm/yyyy')<=TO_DATE(:EN,'dd/mm/yyyy'))                                                                                                                                                                                                                                          
   5 - filter("Y">=TO_NUMBER(:A) AND "Y"<=TO_NUMBER(:B) AND                                                                                                                                                                                                                                                  
              "X">=TO_DATE(:ST,'dd/mm/yyyy') AND "X"<=TO_DATE(:EN,'dd/mm/yyyy'))   

Như bạn có thể thấy, có thêm một filter hoạt động khi bạn sử dụng các biến liên kết xuất hiện trước sort order by stopkey . Điều này xảy ra sau khi truy cập chỉ mục. Điều này là kiểm tra xem các giá trị cho các biến sẽ cho phép dữ liệu được trả về (biến đầu tiên ở giữa của bạn thực sự có giá trị thấp hơn biến thứ hai). Điều này không cần thiết khi sử dụng các ký tự vì trình tối ưu hóa đã biết rằng 50 nhỏ hơn 100 (trong trường hợp này). Tuy nhiên, nó không biết liệu:a có nhỏ hơn:b tại thời điểm phân tích cú pháp hay không.

Chính xác tại sao điều này thì tôi không biết. Đó có thể là thiết kế có chủ đích của Oracle - chẳng ích gì khi thực hiện việc kiểm tra phím tắt nếu các giá trị được đặt cho các biến dẫn đến không có hàng - hoặc chỉ là một sự giám sát.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Oracle SQL - Lấy giá trị từ nhiều hàng

  2. Chuỗi cập nhật trong Oracle với mili giây

  3. Loại trừ chuỗi con từ chuỗi đã cho

  4. SQL * Plus CSV Xuất chậm hơn SQL Developer

  5. Oracle SQL- Gắn cờ các bản ghi dựa trên ngày tháng so với lịch sử của bản ghi