Sự khác biệt lớn về hiệu suất khi sử dụng nhóm theo nhóm so với nhóm riêng biệt


80

Tôi đang thực hiện một số thử nghiệm trên HSQLDBmáy chủ có bảng chứa 500 000 mục nhập. Bảng không có chỉ số. Có 5000 khóa kinh doanh riêng biệt. Tôi cần một danh sách trong số họ. Đương nhiên, tôi bắt đầu với một DISTINCTtruy vấn:

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

Nó mất khoảng 90 giây !!!

Sau đó, tôi đã thử sử dụng GROUP BY:

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

Và mất 1 giây !!!

Cố gắng tìm ra sự khác biệt mà tôi đã chạy EXLAIN PLAN FORnhưng dường như nó cung cấp cùng một thông tin cho cả hai 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

CHỈNH SỬA : Tôi đã làm các bài kiểm tra bổ sung. Với 500 000 bản ghi HSQLDBvới tất cả các khóa nghiệp vụ riêng biệt, hiệu suất của DISTINCTgiờ đây tốt hơn - 3 giây, so với GROUP BYkhoảng 9 giây.

Trong MySQLcả hai truy vấn đều giống nhau:

MySQL: 500 000 hàng - 5000 khóa nghiệp vụ riêng biệt: Cả hai truy vấn: 0,5 giây MySQL: 500 000 hàng - tất cả các khóa nghiệp vụ riêng biệt: SELECT DISTINCT ...- 11 giây SELECT ... GROUP BY business_key- 13 giây

Vì vậy, vấn đề 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 lại có sự khác biệt lớn như vậy.


2
xin vui lòng hiển thị các kết quả của EXPLAIN PLANVÀ thử chạy các DISTINCTtruy vấn sau khi bạn chạy GROUP BYđể xem liệu có lẽ một số bộ nhớ đệm được làm lệch thời gian ...
Yahia

Với việc bạn nhận được cùng một kế hoạch 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ớ đệm.
a'r

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

Tôi có một ý tưởng, nhưng tôi thực sự không chắc chắn - hãy thử SELECT DISTINCT business_key FROM (SELECT business_key FROM memory WHERE concept <> 'case' or attrib <> 'status' or value <> 'closed')- điều này phải thể hiện cùng hiệu suất mà bạn thấy với GROUP BYNẾU ý tưởng của tôi là đúng.
Yahia

@Yahia: vẫn rất chậm - 94 giây. Tôi sẽ chạy các truy vấn tương tự trong MySQL để xem những gì sẽ hiển thị
Martin Dimitrov

Câu trả lời:


76

Hai truy vấn thể hiện cùng một câu hỏi. Rõ ràng trình tối ưu hóa truy vấn chọn hai kế hoạch thực thi khác nhau. Tôi đoán rằng distinctcách tiếp cận được thực hiện như sau:

  • Sao chép tất cả các business_keygiá trị vào 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ả lại từng mục khác với bảng trước đó

group bythể được thực hiện như:

  • Quét toàn bộ bảng, lưu trữ từng giá trị business keytrong bảng băm
  • Trả lại các khóa của bảng băm

Phương pháp đầu tiên tối ưu hóa việc sử dụng bộ nhớ: nó vẫn hoạt động 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 tốc độ, nhưng có thể yêu cầu 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 nên phương pháp thứ hai hoạt động tốt hơn phương pháp đầu tiên. Không có gì lạ khi thấy sự khác biệt về hiệu suất 10x hoặc thậm chí 100x giữa hai kế hoạch thực thi.


Cảm ơn vi đa trả lơi. Suy đoán của bạn có rõ ràng từ EXPLAINđầu ra không? Cả hai đều giống nhau đối với tôi.
Martin Dimitrov

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

Như câu trả lời đã chỉ ra, phương pháp thứ hai sử dụng nhiều bộ nhớ hơn và có thể tấn công thu gom rác (GC) quá thường xuyên. Nếu bạn tăng phân bổ bộ nhớ JVM, sẽ không có sự khác biệt lớn giữa hai thời gian truy vấn.
fredt

Tôi đã thực hiện kiểm tra bổ sung bằng cách nhập tất cả các khóa riêng biệt trong bảng (xem ở trên). Bạn có nghĩ rằng kết quả chứng minh quan điểm của bạn? Cảm ơn rất nhiều.
Martin Dimitrov,

2
Chuyên gia về SME có thể giải thích chi tiết hơn về vấn đề này với các ví dụ không ... Tôi đã gặp vấn đề này nhiều lần nhưng dường như không giải quyết được nó ... Tôi biết cách khắc phục nhưng tôi muốn biết làm thế nào và TẠI SAO
singhswat
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.