Thông tin tham khảo về việc thực thi truy vấn

Trang này giải thích đầu ra của một truy vấn được thực thi bằng Query Explain. Để tìm hiểu cách thực thi một truy vấn bằng Query Explain, hãy xem bài viết Phân tích quá trình thực thi truy vấn bằng Query Explain.

Các khái niệm chung

Các khái niệm và thuật ngữ chung sau đây được sử dụng trong toàn bộ cây thực thi.

Hàng và bản ghi

Các thuật ngữ hàngbản ghi được dùng để chỉ chung một tài liệu hoặc mục nhập chỉ mục.

Biến

$ biểu thị một biến được tạo hoặc tham chiếu trong cây thực thi. Ví dụ: $foo_1. Các biến này thường được dùng để tham chiếu đến nội dung của một tài liệu hoặc giá trị của một biểu thức được đánh giá trong quá trình thực thi một truy vấn.

Các biến nội bộ sau đây có thể xuất hiện trong các nút thực thi:

  • $__key__ – khoá là giá trị nhận dạng nội bộ cho một tài liệu. Đây là giá trị nhận dạng tuyệt đối, duy nhất với dự án, cơ sở dữ liệu và đường dẫn đầy đủ của tài liệu.
  • $__id__ – mã nhận dạng là giá trị nhận dạng duy nhất cho một tài liệu trong bộ sưu tập của tài liệu đó. Giá trị này là duy nhất trong một bộ sưu tập.
  • $rid – mã nhận dạng hàng là giá trị nhận dạng nội bộ cho một tài liệu trong bộ nhớ. Giá trị này là duy nhất trong một bộ sưu tập.

Hãy xem xét một ví dụ trong đó nút Compute được dùng để tính toán __id__ từ tài liệu __key__:

Compute
    |  $__id__1: _id($__key__)
    |  records returned: 1

Ràng buộc và phạm vi

Một số nút quét sử dụng các thuộc tính constraintsranges để mô tả phạm vi giá trị được quét. Các thuộc tính này sử dụng định dạng cây phạm vi chứa danh sách giá trị. Các giá trị này tương ứng với danh sách khoá được sắp xếp xuất hiện trong định nghĩa chỉ mục. Ví dụ: phạm vi đầu tiên xuất hiện trong cây, ở đây là (1..5], tương ứng với các ràng buộc trên khoá đầu tiên, ở đây là a, trong danh sách khoá được sắp xếp:

| index: type=CollectionGroupIndex, id=CICAgOjXh#EK, keys=[a ASC, b ASC, __key__ ASC]
| constraints: /
               |----(1..5]
                    |----[1L]

Mỗi cấp độ thụt lề cho biết ràng buộc áp dụng cho khoá tiếp theo trong danh sách. Dấu ngoặc vuông biểu thị một phạm vi bao gồm, dấu ngoặc tròn là một phạm vi loại trừ. Trong trường hợp này, ràng buộc được chuyển thành 1 < "a" <= 5"b" = 1.

Trong ví dụ sau đây có nhiều nhánh cho a, ràng buộc tương ứng với 1 < a <= 5 OR a = 10:

| constraints: /
               |----(1L, 5L]
               |----[10L]

Biến khoá

Trong một số nút quét (chẳng hạn như SequentialScan), có cả danh sách khoá như một phần của thuộc tính index và thuộc tính keys riêng biệt trong nút Scan. Thuộc tính keys trong nút Scan biểu thị tên biến của mỗi khoá trong định nghĩa chỉ mục, theo thứ tự. Bạn có thể sử dụng các biến để tham chiếu đến các giá trị thời gian chạy của trường được quét ở xa hơn trong cây thực thi.

Trong ví dụ sau đây, giá trị của trường user cho tài liệu hiện tại ánh xạ đến biến $user_1 và giá trị của date_placed đến $date_placed_1.

index: type=CollectionGroupIndex, id=CICAgOjXh4EK, keys=[user ASC, date_placed ASC, __key__ ASC]
keys: [user ASC, date_placed ASC, __key__ ASC]

Nút thực thi

Cây thực thi truy vấn có thể chứa các nút sau.

SeekingScan

Đại diện cho một quá trình quét động, trong đó các hàng được trả về có thể không nằm trong một phạm vi tuần tự duy nhất của chỉ mục và phải thực hiện nhiều lần quét riêng biệt để đáp ứng truy vấn.

Ví dụ: một truy vấn trong đó a tồn tại và b bằng 1 hoạt động trên một chỉ mục của ["a" ASC, "b" ASC] sẽ cần quét và trả về một phạm vi riêng biệt, có khả năng không tuần tự cho mỗi giá trị riêng biệt của a. Quá trình này hiệu quả hơn TableScan đầy đủ, nhưng kém hiệu quả hơn SequentialScan duy nhất trên một chỉ mục tổng hợp của ["b" ASC, "a" ASC].

• SeekingScan
| constraints: /
               |----(-∞..+∞)
                    |----[1L]
| index: type=CollectionGroupIndex, id=CAE, keys=[user ASC, quantity ASC, __key__ ASC]
| keys: [user ASC, quantity ASC, __key__ ASC]
| properties: Selection { user }
| records returned: 1
| records scanned: 1

SequentialScan

Đại diện cho một quá trình quét một phạm vi tuần tự, tĩnh của các hàng trong bộ nhớ có thể được thực hiện trong một thao tác đọc.

key ordering length đề cập đến số lượng khoá phải được giữ nguyên và trả về theo thứ tự khoá ban đầu. Đối với lược đồ [k1, k2, k3], độ dài sắp xếp khoá là 0 có nghĩa là quá trình quét có thể trả về theo bất kỳ thứ tự nào, 1 có nghĩa là sắp xếp theo k1, nhưng các hàng có cùng giá trị k1 có thể có bất kỳ thứ tự nào, 3 trả về tài liệu theo đúng thứ tự đã sắp xếp.

• SequentialScan
| index: type=CollectionGroupIndex, id=CAE, keys=[user ASC, date_placed ASC, __key__ ASC]
| key ordering length: 3
| keys: [user ASC, date_placed ASC, __key__ ASC]
| limit: 10
| properties: Selection { a }
| ranges: /
| records returned: 1
| records scanned: 1

UniqueScan

Đại diện cho một quá trình quét một phạm vi tuần tự, tĩnh của các hàng trong bộ nhớ có tính năng loại bỏ trùng lặp hàng trong bộ nhớ.

• UniqueScan
| index: type=CollectionGroupIndex, id=CAE, keys=[user ASC, date_placed ASC, __key__ ASC]
| keys: [user ASC, date_placed ASC, __key__ ASC]
| properties: Selection { a }
| ranges: /
          |----(-∞..+∞)
| records returned: 1
| records scanned: 1

IndexSeek

Đại diện cho một quá trình quét động, trong đó các hàng được trả về có thể được tham số hoá bằng dữ liệu thời gian chạy và có thể không nằm trong một phạm vi tuần tự duy nhất của chỉ mục. Ngoài ra, có thể thực hiện nhiều lần quét riêng biệt để đáp ứng truy vấn.

Ví dụ: một truy vấn trong đó user bằng $user_iddate_placed bằng "2025-08-10" chạy trên một chỉ mục của ["user" ASC, "date_placed" ASC], sẽ sử dụng giá trị của biến $user_id tại thời gian chạy và ràng buộc "2025-08-10" trên date_placed để hạn chế phạm vi quét.

• IndexSeek
| index: type=CollectionGroupIndex, id=CAE, keys=[user ASC, date_placed ASC, __key__ ASC]
| fields: [$user_1 ASC, $date_placed_1 ASC, $rid ASC]
| key: $key_1
| filter: $eq($user_1, $user_id) AND $eq($date_placed_1, "2025-08-10")
| records returned: 1
| records scanned: 1

Tìm nạp

Kết hợp ngược giá trị nhận dạng của hàng được cung cấp với nội dung hàng thực tế từ bộ nhớ chính. Bạn phải sử dụng Fetch nếu một nút mẹ (hoặc kết quả truy vấn cuối cùng) yêu cầu một tập hợp con của các trường từ tài liệu.

• Fetch
|  order: PRESERVE_INPUT_ORDER
|  peak memory usage: 4.00 KiB (4,096 B)
|  properties: *
|  records returned: 1

TableScan

Quá trình quét đầy đủ, không theo thứ tự của một bộ sưu tập. Được dùng khi một truy vấn được chạy mà không có chỉ mục được liên kết.

Thứ tự có thể là STABLE hoặc UNDEFINED, trong đó STABLE biểu thị một thứ tự xác định.

• TableScan
|  order: STABLE
|  properties: *
|  records returned: 1
|  records scanned: 1
|  source: (default)#/**/collection

Áp dụng

Thực hiện thao tác kết hợp giữa hai tập dữ liệu (inputmap) bằng cách lặp lại từng hàng của input và đối với mỗi hàng, quét và trả về kết quả từ phía map.

join_type cho biết loại kết hợp. Ví dụ: LEFT_OUTER có nghĩa là tất cả các hàng từ input đều được đưa vào ít nhất một lần trong đầu ra. Nếu một hàng input không tìm thấy kết quả nào từ phía map, thì hàng đó vẫn sẽ được đưa vào, với các giá trị null cho các cột từ phía map.

• Apply
|  join_type: LEFT_OUTER
|
└── • input tree
|     ...
└── • map tree
      ...

HashAggregate

Triển khai dựa trên hàm băm của các thao tác tổng hợp. Yêu cầu hiện thực hoá toàn bộ nhóm trong bộ nhớ trước khi trả về kết quả và không được vượt quá giới hạn bộ nhớ truy vấn.

• HashAggregate
|  aggregations: [sum($b_1) AS total]
|  groups: [$a_1]
|  peak memory usage: 4.00 KiB (4,096 B)
|  records returned: 0

StreamAggregate

Nút tổng hợp chuyên biệt chỉ duy trì trạng thái cho một nhóm tại một thời điểm, giảm mức sử dụng bộ nhớ cao nhất. Được dùng khi nút con cơ bản sẽ trả về các nhóm theo tuần tự. Ví dụ: khi nhóm theo các giá trị riêng biệt của một trường trong khi sử dụng chỉ mục trên trường đó.

• StreamAggregate
|  keys: [foo ASC, bar ASC]
|  properties: Selection { baz }
|  aggregations: [$sum($foo_1) AS baz]

MajorSort

Thực hiện thao tác sắp xếp trên một tập hợp thuộc tính cố định. Hiện thực hoá tất cả các bản ghi trong bộ nhớ cùng một lúc và trả về các giá trị đã sắp xếp theo thứ tự, kích thước của tập hợp sắp xếp bị giới hạn bởi giới hạn bộ nhớ truy vấn.

Khi cung cấp giới hạn tiếp theo, thuật toán sắp xếp k hàng đầu được dùng để giảm mức sử dụng bộ nhớ. Với thuật toán này, bạn có thể sắp xếp trên một tập hợp bản ghi lớn tuỳ ý miễn là bộ nhớ được dùng để lưu trữ k phần tử được xem xét không vượt quá giới hạn.

• MajorSort
|  fields: [a ASC, b DESC]
|  limit: 10
|  peak memory usage: 4.00 KiB (4,096 B)
|  records returned: 1

Concat

Nối kết quả của nhiều nút con và trả về kết quả cho nút mẹ. Nút này không loại bỏ trùng lặp các kết quả xuất hiện trong nhiều nút con và thứ tự của các kết quả được trả về là không xác định.

• Concat
├── • Fetch
...
├── • Fetch

Compute

Đánh giá một tập hợp biểu thức, gán kết quả cho một tập hợp biến.

• Compute
|  $user_1: user
|  $full_name_1: str_concat($first_name_1, " ", $last_name_1)
|  $address_1: UNSET
|  records returned: 1

Bộ lọc

Chọn lọc trả về các hàng nếu và chỉ khi các hàng đó khớp với biểu thức được cung cấp.

• Filter
|  expression: $eq(foo, "bar")
|  records returned: 1

RecordCount

Đếm số hàng do nút con tạo ra và phát số lượng hiện tại cho biến được chỉ định trong thuộc tính count.

• RecordCount
|  count: $row_number_1
|  records returned: 1

Giá trị

Tạo một chuỗi giá trị cố định để xử lý. Được dùng chủ yếu khi một tập hợp danh sách tài liệu được cung cấp làm giá trị đầu vào cho một truy vấn.

• Values
| expression: [{__key__=/col/1}, {__key__=/col/2}]

Unnest

Huỷ lồng giá trị do nút con tạo ra.

• Unnest
|  expression: foo AS unnested_foo

Giới hạn

Giới hạn số hàng được trả về cho nút mẹ.

• Limit
|  limit: 10
|  records returned: 1

Bù trừ

Bỏ qua một số lượng hàng do nút con tạo ra.

• Offset
|  offset: 10
|  records returned: 1