2016-12-21 17 views
6

Tôi có hai bảng có cột SessionOrder. Cột này là kiểu dữ liệu số nguyên và có chỉ mục sau: CREATE INDEX OSIDX_<internal name> ON <Entity>.INNER THAM GIA hiệu suất với điều kiện '<' or '>'

tôi đang thực hiện các truy vấn sau đây:

SELECT i_0.rn, i_1.rn 
FROM (
    SELECT "RawEvent"."SessionOrder" as rn 
    FROM "RawEvent" i_0 
    WHERE something = 12 
) 
INNER JOIN (
    SELECT "RawEvent"."SessionOrder" as rn 
    FROM "RawEvent" i_1 
    WHERE something = 14 
) ON i_0.rn > i_1.rn 

Vấn đề của truy vấn này là ON i_0.rn > i_1.rn mà được quá chậm và thời gian ra. Tôi đã thay thế nó bằng ON i_0.rn = i_1.rn và nó rất nhanh nhưng rõ ràng không tạo ra kết quả mong đợi.

Có ai đó biết cách tăng hiệu suất của truy vấn này tránh thời gian chờ không? Mục tiêu khác của câu hỏi này là để hiểu tại sao nó có hiệu suất kém với ON i_0.rn > i_1.rn.

PS: Không thể tăng thời gian chờ

+1

Kế hoạch thực hiện cho thấy nó đang hoạt động như thế nào? Mỗi truy vấn phụ tìm bao nhiêu hàng? (Tại sao bạn sử dụng các truy vấn phụ thay vì chỉ tham gia các bảng? Và điều này không giống như cú pháp Oracle tại thời điểm này). –

+0

Đây không phải là truy vấn hợp lệ. Các bí danh của bảng không được định nghĩa trong phạm vi 'ON i_0.rn> i_1.rn' –

+3

Tôi đồng ý với Alex, điều này chắc chắn không phải cú pháp Oracle. Điều đó nói rằng, đây gần như là một tham gia Descartes. Bạn có thực sự có ý định tham gia mỗi hàng ít hơn i_o.rn để i_o? Ví dụ, SQL này trả về 4.950 hàng: với aset như (chọn rownum r từ dba_objects nơi rownum <101) chọn a.r, b.r từ aset a tham gia bên trong aset b trên a.r> b.r. –

Trả lời

3

Hãy kiểm tra trước nếu bạn thực sự sử dụng cơ sở dữ liệu Oracle. Cú pháp của SQL của bạn gợi ý RDBMS khác hoặc một số prepocessor.

Để có ấn tượng về những gì bạn có thể mong đợi từ các loại truy vấn như vậy, bạn có thể sử dụng ví dụ giả như sau.

Tạo dữ liệu mẫu

create table myTab as 
with mySeq as 
(select rownum SessionOrder from dual connect by level <= 10000) 
select 12 something, SessionOrder from mySeq union all 
select 14 something, SessionOrder from mySeq 
; 

này tạo ra cả subsources mỗi 10.000 chuỗi bắt đầu từ 1-10,000.

thử nghiệm Query

create table myRes as 
select a.SessionOrder rn0, b.SessionOrder rn1 
from myTab a join myTab b on a.SessionOrder > b.SessionOrder and 
a.something = 12 and b.something = 14; 

Tạo 49.995.000 hàng trong ít mà 30 giây.

Nếu bạn mong đợi nhận được kết quả lớn như vậy trong thời gian ít hơn nhiều, bạn sẽ cần tối ưu hóa nâng cao. Nếu không biết dữ liệu của bạn và yêu cầu không có lời khuyên generll là có thể.

1

Được đề xuất tôi đã cố gắng giải quyết vấn đề với chiến lược khác có hiệu suất cao hơn.

Mặc dù giải pháp đơn giản này, tôi không hiểu tại sao truy vấn ban đầu lại quá chậm. Tôi nghĩ rằng động cơ Oracle không sử dụng các chỉ mục.

SELECT i_0."SessionOrder", i_1."SessionOrder" 
FROM "RawEvent" i_0 
INNER JOIN "RawEvent" i_1 ON i_0."SessionOrder" < i_1."SessionOrder" 
WHERE i_0."something" = 12 AND i_1."something" = 14 
+2

Truy vấn đó không trả lại kết quả tương tự như kết quả ban đầu của bạn - bạn sẽ phải thay thế 'OR' bằng' AND' để nhận kết quả tương tự. Ngoài ra, nếu không có thông tin bổ sung về dữ liệu đầu vào của bạn (số lượng hàng, phân phối thứ gì đó/SessionOrder), bạn không thể biết liệu nó có tạo ra sự khác biệt hay không nếu trình tối ưu hóa sử dụng chỉ mục. Nó có thể rất tốt quyết định rằng một bảng đầy đủ quét là thích hợp hơn nếu dữ liệu của bạn là rất nhiều skewed. –

+0

@Helder Tôi đã thêm một câu trả lời khác giải quyết các mối quan tâm về chỉ mục của bạn ... –

0

truy vấn của bạn thực hiện ba nhiệm vụ:

1) tìm nạp dữ liệu cho cả các tập con (12 và 14)

2) tham gia các dữ liệu và

3) vượt qua các kết quả để khách hàng

Lưu ý rằng quyền truy cập chỉ mục (mà bạn nghi ngờ gây ra sự cố) chỉ liên quan đến bước 1. Vì vậy, để có được ấn tượng tốt hơn điều đầu tiên là nhận ra sự phân bố thời gian trôi qua giữa ba bước. Điều này có thể được thực hiện sử dụng SQL * Plus (Tôi đang sử dụng các dữ liệu được tạo giống như trong câu trả lời trước của tôi)

Data Access

Như bàn của tôi không có chỉ số, biểu diễn một count (*) thực hiện một FULL TABLE SCAN. Vì vậy, trong một trường hợp xấu nhất một hai lần thời gian được sử dụng để có được dữ liệu.

SQL> set timi on 
SQL> set autotrace on 
SQL> select count(*) from mytab; 

    COUNT(*) 
---------- 
    20000 

Elapsed: 00:00:01.13 

Execution Plan 
---------------------------------------------------------- 
Plan hash value: 3284627250 

-------------------------------------------------------------------- 
| Id | Operation   | Name | Rows | Cost (%CPU)| Time  | 
-------------------------------------------------------------------- 
| 0 | SELECT STATEMENT |  |  1 | 5472 (1)| 00:00:01 | 
| 1 | SORT AGGREGATE |  |  1 |   |   | 
| 2 | TABLE ACCESS FULL| MYTAB | 20000 | 5472 (1)| 00:00:01 | 
-------------------------------------------------------------------- 

FTS sẵn sàng sau khoảng một giây, để nhận được cả hai nhóm aprox. hai giây trôi qua.

THAM GIA

Các trôi qua thời gian để tham gia lon bằng mô phỏng với một CTAS của truy vấn tham gia.

SQL> create table myRes as 
    2 select a.SessionOrder rn0, b.SessionOrder rn1 
    3 from myTab a join myTab b on a.SessionOrder > b.SessionOrder and 
    4 a.something = 12 and b.something = 14; 

Table created. 

Elapsed: 00:00:23.65 

Tham gia trả về gần 50M hàng (do lớn hơn điều kiện) và mất khoảng 21 giây (tôi trừ 2 giây để truy cập dữ liệu).

PASS dữ liệu cho khách hàng

Chúng tôi sử dụng tùy chọn set autotrace traceonly để ngăn chặn đầu ra của các truy vấn trên màn hình của khách hàng, nhưng dữ liệu được chuyển giao, vì vậy chúng tôi có thể đo thời gian. (Nếu bạn làm cho kết quả trên màn hình, thời gian sẽ còn cao hơn nhiều)

SQL> SET ARRAYSIZE 5000 
SQL> set autotrace traceonly 
SQL> select a.SessionOrder rn0, b.SessionOrder rn1 
    2 from myTab a join myTab b on a.SessionOrder > b.SessionOrder and 
    3 a.something = 12 and b.something = 14; 

49995000 rows selected. 

Elapsed: 00:03:03.89 

Execution Plan 
---------------------------------------------------------- 
Plan hash value: 2857240533 

----------------------------------------------------------------------------- 
| Id | Operation   | Name | Rows | Bytes | Cost (%CPU)| Time  | 
----------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT |  | 49M| 667M| 11077 (2)| 00:00:01 | 
| 1 | MERGE JOIN   |  | 49M| 667M| 11077 (2)| 00:00:01 | 
| 2 | SORT JOIN   |  | 10000 | 70000 | 5473 (1)| 00:00:01 | 
|* 3 | TABLE ACCESS FULL| MYTAB | 10000 | 70000 | 5472 (1)| 00:00:01 | 
|* 4 | SORT JOIN   |  | 10000 | 70000 | 5473 (1)| 00:00:01 | 
|* 5 | TABLE ACCESS FULL| MYTAB | 10000 | 70000 | 5472 (1)| 00:00:01 | 
----------------------------------------------------------------------------- 

Dưới đây là thời gian nhất dành khoảng 2:40 phút

Tóm tắt

Vì vậy, trong kịch bản từ tổng số 3 phút + chỉ khoảng 2 giây là chi tiêu cho truy cập dữ liệu (hoặc khoảng 1%). Thậm chí nếu bạn cắt quyền truy cập dữ liệu xuống một phần mười - bạn sẽ thấy hầu như không có sự khác biệt. Vấn đề nằm trong sự tham gia và thậm chí nhiều hơn trong việc chuyển dữ liệu cho khách hàng.

Khi Index có thể giúp

Và tất nhiên nó phụ thuộc ...

Trong một trường hợp rất đặc biệt, nơi bạn có một bảng rất lớn với dữ liệu rất ít với something in (12,14) bạn có thể lợi nhuận từ chỉ mục được xác định trên một cái gì đó SessionOrder. Điều này chỉ cho phép sử dụng chỉ số chỉ truy cập vào bỏ qua bảng dữ liệu.

Các vấn đề liên quan