Trang này giải thích kết quả của một truy vấn được thực thi bằng tính năng Giải thích truy vấn. Để tìm hiểu cách thực thi một truy vấn bằng tính năng Giải thích truy vấn, hãy xem bài viết Phân tích việc thực thi truy vấn bằng tính năng Giải thích truy vấn.
Khái niệm chung
Các khái niệm và thuật ngữ phổ biến 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àng và bả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 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ộ của một tài liệu. Đây là giá trị nhận dạng riêng biệt, tuyệt đối 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 riêng biệt của một tài liệu trong tập hợ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ộ của 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
Các quy tắc ràng buộc và phạm vi
Một số nút quét sử dụng các thuộc tính constraints và ranges để 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, trong đó có một danh sách các giá trị. Các giá trị này tương ứng với danh sách khoá theo thứ tự xuất hiện trong định nghĩa chỉ mục. Ví dụ: dải ô đầu tiên xuất hiện trong cây, ở đây là (1..5], tương ứng với các quy tắc ràng buộc đối với khoá đầu tiên, ở đây là a, trong danh sách khoá theo thứ tự:
| 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 quy tắc 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 dải ô bao gồm, dấu ngoặc tròn là một dải ô loại trừ. Trong trường hợp này, quy tắc ràng buộc sẽ chuyển thành 1 < "a" <= 5 và "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 chính
Trong một số nút quét (chẳng hạn như SequentialScan), có cả danh sách khoá trong thuộc tính index và một 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 giá trị thời gian chạy của trường được quét ở phía trên trong cây thực thi.
Trong ví dụ sau, giá trị của trường user cho tài liệu hiện tại liên kết với biến $user_1 và giá trị của date_placed liên kết với $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
Biểu thị một lần quét động, trong đó các hàng được trả về có thể không nằm trong một dải ô 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 chỉ mục của ["a" ASC, "b" ASC], sẽ cần quét và trả về một dải riêng biệt, có thể không tuần tự cho mỗi giá trị riêng biệt của a.
Cách này hiệu quả hơn so với TableScan đầy đủ, nhưng kém hiệu quả hơn so với một SequentialScan trên chỉ mục kết 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 lần quét dải ô tĩnh, tuần tự trong bộ nhớ có thể được thực hiện trong một thao tác đọc.
key ordering length là số lượng khoá phải được giữ nguyên và trả về theo thứ tự khoá ban đầu. Đối với giản đồ [k1, k2, k3], độ dài thứ tự khoá là 0 có nghĩa là quá trình quét có thể trả về theo thứ tự bất kỳ, 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ể theo thứ tự bất kỳ, 3 trả về tài liệu theo thứ tự sắp xếp chính xác.
• 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 lần quét dải hàng tĩnh, tuần tự trong bộ nhớ có 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
Biểu thị một lần 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 dải tuần tự của chỉ mục, đồng thời 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_id và date_placed bằng "2025-08-10" chạy trên chỉ mục ["user" ASC, "date_placed" ASC] sẽ sử dụng giá trị của biến $user_id trong thời gian chạy và quy tắc 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
Nối 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. Fetch là bắt buộc nếu 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ác trường trong tài liệu.
• Fetch
| order: PRESERVE_INPUT_ORDER
| peak memory usage: 4.00 KiB (4,096 B)
| properties: *
| records returned: 1
TableScan
Quét toàn bộ, không theo thứ tự của một tập hợp. Được dùng khi một truy vấn được chạy mà không có chỉ mục liên kết.
Thứ tự có thể là STABLE hoặc UNDEFINED, trong đó STABLE biểu thị thứ tự tất định.
• TableScan
| order: STABLE
| properties: *
| records returned: 1
| records scanned: 1
| source: (default)#/**/collection
Áp dụng
Thực hiện phép nối giữa hai tập dữ liệu (input và map) bằng cách lặp lại
qua 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 phép nối. Ví dụ: LEFT_OUTER có nghĩa là tất cả các hàng trong input được đưa vào kết quả ít nhất một lần.
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 các thao tác tổng hợp dựa trên hàm băm. Yêu cầu cụ thể 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úp 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 nhóm thuộc tính cố định. Hiện thực hoá tất 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 hạn mức bộ nhớ truy vấn.
Khi có giới hạn tiếp theo, thuật toán sắp xếp top-k sẽ được dùng để giảm mức sử dụng bộ nhớ. Nhờ đó, bạn có thể thực hiện các thao tác sắp xếp trên một tập hợp bản ghi lớn tuỳ ý, miễn là bộ nhớ 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ỏ kết quả trùng lặp xuất hiện trong nhiều nút con và thứ tự của kết quả được trả về là không xác định.
• Concat
├── • Fetch
...
├── • Fetch
Điện toán
Đá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
Trả về các hàng một cách có chọn lọc 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 các giá trị cố định để xử lý. Chủ yếu được dùng khi một danh sách tài liệu nhất định được cung cấp làm dữ liệu đầ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ề nút mẹ.
• Limit
| limit: 10
| records returned: 1
Khoảng bù
Bỏ qua một số hàng nhất định do nút con tạo ra.
• Offset
| offset: 10
| records returned: 1