2011-10-30 23 views
51

Tôi đang thực hiện một số xét nghiệm trên máy chủ HSQLDB với một bảng chứa 500 000 mục. Bảng không có chỉ mục. Có 5000 khóa kinh doanh riêng biệt. Tôi cần một danh sách của họ. Đương nhiên, tôi bắt đầu với truy vấn DISTINCT:khổng lồ khác biệt hiệu suất khi sử dụng nhóm bằng vs biệt

SELECT DISTINCT business_key FROM memory WHERE 
    concept <> 'case' or 
    attrib <> 'status' or 
    value <> 'closed' 

Mất khoảng 90 giây !!!

Sau đó, tôi cố gắng sử dụng GROUP BY:

SELECT business_key FROM memory WHERE 
     concept <> 'case' or 
     attrib <> 'status' or 
     value <> 'closed' 
GROUP BY business_key 

Và phải mất 1 giây !!!

Đang cố gắng để tìm ra sự khác biệt Tôi chạy EXLAIN PLAN FOR nhưng có vẻ như để cung cấp cho các thông tin tương tự cho cả truy vấn.

EXLAIN PLAN FOR DISTINCT ...

isAggregated=[false] 
columns=[ 
    COLUMN: PUBLIC.MEMORY.BUSINESS_KEY 
] 
[range variable 1 
    join type=INNER 
    table=MEMORY 
    alias=M 
    access=FULL SCAN 
    condition = [ index=SYS_IDX_SYS_PK_10057_10058 
    other condition=[ 
    OR arg_left=[ 
    OR arg_left=[ 
     NOT_EQUAL arg_left=[ 
     COLUMN: PUBLIC.MEMORY.CONCEPT] arg_right=[ 
     VALUE = case, TYPE = CHARACTER]] arg_right=[ 
     NOT_EQUAL arg_left=[ 
     COLUMN: PUBLIC.MEMORY.ATTRIB] arg_right=[ 
     VALUE = status, TYPE = CHARACTER]]] arg_right=[ 
    NOT_EQUAL arg_left=[ 
     COLUMN: PUBLIC.MEMORY.VALUE] arg_right=[ 
     VALUE = closed, TYPE = CHARACTER]]] 
    ] 
]] 
PARAMETERS=[] 
SUBQUERIES[] 
Object References 
PUBLIC.MEMORY 
PUBLIC.MEMORY.CONCEPT 
PUBLIC.MEMORY.ATTRIB 
PUBLIC.MEMORY.VALUE 
PUBLIC.MEMORY.BUSINESS_KEY 
Read Locks 
PUBLIC.MEMORY 
WriteLocks 

EXLAIN PLAN FOR SELECT ... GROUP BY ...

isDistinctSelect=[false] 
isGrouped=[true] 
isAggregated=[false] 
columns=[ 
    COLUMN: PUBLIC.MEMORY.BUSINESS_KEY 
] 
[range variable 1 
    join type=INNER 
    table=MEMORY 
    alias=M 
    access=FULL SCAN 
    condition = [ index=SYS_IDX_SYS_PK_10057_10058 
    other condition=[ 
    OR arg_left=[ 
    OR arg_left=[ 
     NOT_EQUAL arg_left=[ 
     COLUMN: PUBLIC.MEMORY.CONCEPT] arg_right=[ 
     VALUE = case, TYPE = CHARACTER]] arg_right=[ 
     NOT_EQUAL arg_left=[ 
     COLUMN: PUBLIC.MEMORY.ATTRIB] arg_right=[ 
     VALUE = status, TYPE = CHARACTER]]] arg_right=[ 
    NOT_EQUAL arg_left=[ 
     COLUMN: PUBLIC.MEMORY.VALUE] arg_right=[ 
     VALUE = closed, TYPE = CHARACTER]]] 
    ] 
]] 
groupColumns=[ 
COLUMN: PUBLIC.MEMORY.BUSINESS_KEY] 
PARAMETERS=[] 
SUBQUERIES[] 
Object References 
PUBLIC.MEMORY 
PUBLIC.MEMORY.CONCEPT 
PUBLIC.MEMORY.ATTRIB 
PUBLIC.MEMORY.VALUE 
PUBLIC.MEMORY.BUSINESS_KEY 
Read Locks 
PUBLIC.MEMORY 
WriteLocks 

EDIT: tôi đã làm các xét nghiệm bổ sung. Với 500 000 bản ghi trong HSQLDB với tất cả các khóa kinh doanh riêng biệt, hiệu suất của DISTINCT hiện tốt hơn - 3 giây, so với GROUP BY mất khoảng 9 giây.

Trong MySQL cả các truy vấn phôi giống nhau:

MySQL: 500 000 hàng - 5 000 phím kinh doanh riêng biệt: Cả hai truy vấn: 0,5 giây MySQL: 500 000 hàng - tất cả các phím kinh doanh riêng biệt: SELECT DISTINCT ...-11 giây SELECT ... GROUP BY business_key - 13 giây

Vì vậy, sự cố chỉ liên quan đến HSQLDB.

tôi sẽ rất biết ơn nếu ai đó có thể giải thích tại sao có sự khác biệt mạnh mẽ như vậy.

+2

vui lòng hiển thị kết quả của 'EXPLAIN PLAN' VÀ thử chạy' DISTINCT'query SAU KHI bạn chạy 'GROUP BY' để xem liệu có lẽ một số bộ nhớ đệm bị lệch thời gian ... – Yahia

+0

Cho bạn nhận được cùng một gói cho mỗi truy vấn, có vẻ như dữ liệu bảng hoặc kết quả đã được lưu vào bộ nhớ cache. –

+0

Tôi đã chạy chúng rất nhiều lần để tin rằng bộ nhớ đệm không phải là vấn đề. Tôi đang đăng đầu ra 'EXLAIN PLAN FOR'. –

Trả lời

54

Hai truy vấn thể hiện cùng một câu hỏi. Dường như trình tối ưu hóa truy vấn chọn hai kế hoạch thực hiện khác nhau.Tôi đoán sẽ là cách tiếp cận distinct được thực hiện như:

  • Sao chép tất cả business_key giá trị cho một bảng tạm thời
  • Sắp xếp bảng tạm thời
  • Quét bảng tạm thời, trở về mỗi mục đó là khác nhau từ một trong những trước khi nó

Các group by có thể được thực hiện như:

  • Quét toàn bộ bảng, lưu trữ mỗi giá trị của business key trong một Hashtable
  • Return các phím của Hashtable

Phương pháp đầu tiên tối ưu hóa cho việc sử dụng bộ nhớ: nó vẫn sẽ thực hiện khá tốt khi một phần của bảng tạm thời phải được hoán đổi. Phương pháp thứ hai tối ưu hóa cho tốc độ, nhưng có khả năng đòi hỏi một lượng lớn bộ nhớ nếu có nhiều khóa khác nhau.

Vì bạn có đủ bộ nhớ hoặc ít khóa khác nhau, phương pháp thứ hai sẽ hoạt động tốt hơn lần đầu tiên. Nó không phải là bất thường để thấy sự khác biệt hiệu suất của 10x hoặc thậm chí 100x giữa hai kế hoạch thực hiện.

+0

Cảm ơn bạn đã trả lời. Có phải đoán của bạn hiển nhiên từ đầu ra 'EXPLAIN'? Cả hai trông giống như tôi. –

+0

Theo như tôi thấy, kế hoạch không chỉ rõ cách nó sẽ thực hiện phép nối. Tôi thậm chí không chắc chắn lý do tại sao nó sẽ thực hiện một tham gia. Có thể phải mất một chuyên gia HSQLDB để đọc kết quả giải nghĩa. – Andomar

+0

Khi câu trả lời cho biết, phương pháp thứ hai sử dụng nhiều bộ nhớ hơn và có thể nhấn vào bộ sưu tập rác (GC) quá thường xuyên. Nếu bạn tăng cấp phát bộ nhớ JVM, sẽ không có sự khác biệt lớn giữa hai lần truy vấn. – fredt

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