1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/// Metrics collected during the course of a transaction.
#[derive(Debug, Default, Copy, Clone)]
pub struct ExecutionMetrics {
/// How many times is an index probed?
///
/// Note that a single btree scan may return many values,
/// but will only result in a single index seek.
pub index_seeks: usize,
/// How many rows are iterated over?
///
/// It is independent of the number of rows returned.
/// A query for example may return a single row,
/// but if it scans the entire table to find that row,
/// this metric will reflect that.
pub rows_scanned: usize,
/// How many bytes are read?
///
/// This metric is incremented anytime we dereference a `RowPointer`.
///
/// For reducers this happens at the WASM boundary,
/// when serializing entire rows via the BSATN encoding.
///
/// In addition to the same BSATN serialization of the output rows,
/// queries will dereference a `RowPointer` for column projections.
/// Such is the case for filters as well as index and hash joins.
///
/// One place where this metric is not tracked is index scans.
/// Specifically the key comparisons that occur during the scan.
pub bytes_scanned: usize,
/// How many bytes are written?
///
/// Note, this is the same as bytes inserted,
/// because deletes just update a free list in the datastore.
/// They don't actually write or clear page memory.
pub bytes_written: usize,
/// How many bytes did we send to clients?
///
/// This is not necessarily the same as bytes scanned,
/// since a single query may send bytes to multiple clients.
///
/// In general, these are BSATN bytes, but JSON is also possible.
pub bytes_sent_to_clients: usize,
/// How many rows were inserted?
pub rows_inserted: u64,
/// How many rows were deleted?
pub rows_deleted: u64,
/// How many rows were updated?
pub rows_updated: u64,
/// How many subscription updates did we execute?
pub delta_queries_evaluated: u64,
/// How many subscriptions had some updates?
pub delta_queries_matched: u64,
/// How many times do we evaluate the same row in a subscription update?
pub duplicate_rows_evaluated: u64,
/// How many duplicate rows do we send in a subscription update?
pub duplicate_rows_sent: u64,
}
impl ExecutionMetrics {
pub fn merge(
&mut self,
ExecutionMetrics {
index_seeks,
rows_scanned,
bytes_scanned,
bytes_written,
bytes_sent_to_clients,
rows_inserted,
rows_deleted,
rows_updated,
delta_queries_evaluated,
delta_queries_matched,
duplicate_rows_evaluated,
duplicate_rows_sent,
}: ExecutionMetrics,
) {
self.index_seeks += index_seeks;
self.rows_scanned += rows_scanned;
self.bytes_scanned += bytes_scanned;
self.bytes_written += bytes_written;
self.bytes_sent_to_clients += bytes_sent_to_clients;
self.rows_inserted += rows_inserted;
self.rows_deleted += rows_deleted;
self.rows_updated += rows_updated;
self.delta_queries_evaluated += delta_queries_evaluated;
self.delta_queries_matched += delta_queries_matched;
self.duplicate_rows_evaluated += duplicate_rows_evaluated;
self.duplicate_rows_sent += duplicate_rows_sent;
}
}
#[cfg(test)]
mod tests {
use super::ExecutionMetrics;
#[test]
fn test_merge() {
let mut a = ExecutionMetrics::default();
a.merge(ExecutionMetrics {
index_seeks: 1,
rows_scanned: 1,
bytes_scanned: 1,
bytes_written: 1,
bytes_sent_to_clients: 1,
rows_inserted: 1,
rows_deleted: 1,
rows_updated: 1,
delta_queries_evaluated: 2,
delta_queries_matched: 3,
duplicate_rows_evaluated: 4,
duplicate_rows_sent: 2,
});
assert_eq!(a.index_seeks, 1);
assert_eq!(a.rows_scanned, 1);
assert_eq!(a.bytes_scanned, 1);
assert_eq!(a.bytes_written, 1);
assert_eq!(a.bytes_sent_to_clients, 1);
assert_eq!(a.rows_inserted, 1);
assert_eq!(a.rows_deleted, 1);
assert_eq!(a.delta_queries_evaluated, 2);
assert_eq!(a.delta_queries_matched, 3);
assert_eq!(a.duplicate_rows_evaluated, 4);
assert_eq!(a.duplicate_rows_sent, 2);
}
}