1 | /* |
2 | Copyright (c) 2015, Facebook, Inc. |
3 | |
4 | This program is free software; you can redistribute it and/or modify |
5 | it under the terms of the GNU General Public License as published by |
6 | the Free Software Foundation; version 2 of the License. |
7 | |
8 | This program is distributed in the hope that it will be useful, |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 | GNU General Public License for more details. |
12 | |
13 | You should have received a copy of the GNU General Public License |
14 | along with this program; if not, write to the Free Software |
15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ |
16 | #pragma once |
17 | |
18 | /* C++ system header files */ |
19 | #include <map> |
20 | #include <memory> |
21 | #include <string> |
22 | #include <unordered_set> |
23 | #include <vector> |
24 | |
25 | /* RocksDB header files */ |
26 | #include "rocksdb/db.h" |
27 | |
28 | /* MyRocks header files */ |
29 | #include "./ha_rocksdb.h" |
30 | |
31 | namespace myrocks { |
32 | |
33 | class Rdb_ddl_manager; |
34 | class Rdb_key_def; |
35 | |
36 | extern std::atomic<uint64_t> rocksdb_num_sst_entry_put; |
37 | extern std::atomic<uint64_t> rocksdb_num_sst_entry_delete; |
38 | extern std::atomic<uint64_t> rocksdb_num_sst_entry_singledelete; |
39 | extern std::atomic<uint64_t> rocksdb_num_sst_entry_merge; |
40 | extern std::atomic<uint64_t> rocksdb_num_sst_entry_other; |
41 | extern my_bool rocksdb_compaction_sequential_deletes_count_sd; |
42 | |
43 | struct Rdb_compact_params { |
44 | uint64_t m_deletes, m_window, m_file_size; |
45 | }; |
46 | |
47 | struct Rdb_index_stats { |
48 | enum { |
49 | INDEX_STATS_VERSION_INITIAL = 1, |
50 | INDEX_STATS_VERSION_ENTRY_TYPES = 2, |
51 | }; |
52 | GL_INDEX_ID m_gl_index_id; |
53 | int64_t m_data_size, m_rows, m_actual_disk_size; |
54 | int64_t m_entry_deletes, m_entry_single_deletes; |
55 | int64_t m_entry_merges, m_entry_others; |
56 | std::vector<int64_t> m_distinct_keys_per_prefix; |
57 | std::string m_name; // name is not persisted |
58 | |
59 | static std::string materialize(const std::vector<Rdb_index_stats> &stats); |
60 | static int unmaterialize(const std::string &s, |
61 | std::vector<Rdb_index_stats> *const ret); |
62 | |
63 | Rdb_index_stats() : Rdb_index_stats({0, 0}) {} |
64 | explicit Rdb_index_stats(GL_INDEX_ID gl_index_id) |
65 | : m_gl_index_id(gl_index_id), m_data_size(0), m_rows(0), |
66 | m_actual_disk_size(0), m_entry_deletes(0), m_entry_single_deletes(0), |
67 | m_entry_merges(0), m_entry_others(0) {} |
68 | |
69 | void merge(const Rdb_index_stats &s, const bool &increment = true, |
70 | const int64_t &estimated_data_len = 0); |
71 | }; |
72 | |
73 | // The helper class to calculate index cardinality |
74 | class Rdb_tbl_card_coll { |
75 | public: |
76 | explicit Rdb_tbl_card_coll(const uint8_t &table_stats_sampling_pct); |
77 | |
78 | public: |
79 | void ProcessKey(const rocksdb::Slice &key, const Rdb_key_def *keydef, |
80 | Rdb_index_stats *stats); |
81 | /* |
82 | * Resets the state of the collector to start calculating statistics for a |
83 | * next index. |
84 | */ |
85 | void Reset(); |
86 | |
87 | /* |
88 | * Cardinality statistics might be calculated using some sampling strategy. |
89 | * This method adjusts gathered statistics according to the sampling |
90 | * strategy used. Note that adjusted cardinality value is just an estimate |
91 | * and can return a value exeeding number of rows in a table, so the |
92 | * returned value should be capped by row count before using it by |
93 | * an optrimizer or displaying it to a clent. |
94 | */ |
95 | void AdjustStats(Rdb_index_stats *stats); |
96 | |
97 | private: |
98 | bool ShouldCollectStats(); |
99 | bool IsSampingDisabled(); |
100 | |
101 | private: |
102 | std::string m_last_key; |
103 | uint8_t m_table_stats_sampling_pct; |
104 | unsigned int m_seed; |
105 | }; |
106 | |
107 | class Rdb_tbl_prop_coll : public rocksdb::TablePropertiesCollector { |
108 | public: |
109 | Rdb_tbl_prop_coll(Rdb_ddl_manager *const ddl_manager, |
110 | const Rdb_compact_params ¶ms, const uint32_t &cf_id, |
111 | const uint8_t &table_stats_sampling_pct); |
112 | |
113 | /* |
114 | Override parent class's virtual methods of interest. |
115 | */ |
116 | |
117 | virtual rocksdb::Status AddUserKey(const rocksdb::Slice &key, |
118 | const rocksdb::Slice &value, |
119 | rocksdb::EntryType type, |
120 | rocksdb::SequenceNumber seq, |
121 | uint64_t file_size); |
122 | |
123 | virtual rocksdb::Status |
124 | Finish(rocksdb::UserCollectedProperties *properties) override; |
125 | |
126 | virtual const char *Name() const override { return "Rdb_tbl_prop_coll" ; } |
127 | |
128 | rocksdb::UserCollectedProperties GetReadableProperties() const override; |
129 | |
130 | bool NeedCompact() const override; |
131 | |
132 | public: |
133 | uint64_t GetMaxDeletedRows() const { return m_max_deleted_rows; } |
134 | |
135 | static void read_stats_from_tbl_props( |
136 | const std::shared_ptr<const rocksdb::TableProperties> &table_props, |
137 | std::vector<Rdb_index_stats> *out_stats_vector); |
138 | |
139 | private: |
140 | static std::string GetReadableStats(const Rdb_index_stats &it); |
141 | |
142 | bool ShouldCollectStats(); |
143 | void CollectStatsForRow(const rocksdb::Slice &key, |
144 | const rocksdb::Slice &value, |
145 | const rocksdb::EntryType &type, |
146 | const uint64_t &file_size); |
147 | Rdb_index_stats *AccessStats(const rocksdb::Slice &key); |
148 | void AdjustDeletedRows(rocksdb::EntryType type); |
149 | |
150 | private: |
151 | uint32_t m_cf_id; |
152 | std::shared_ptr<const Rdb_key_def> m_keydef; |
153 | Rdb_ddl_manager *m_ddl_manager; |
154 | std::vector<Rdb_index_stats> m_stats; |
155 | Rdb_index_stats *m_last_stats; |
156 | static const char *INDEXSTATS_KEY; |
157 | |
158 | // last added key |
159 | std::string m_last_key; |
160 | |
161 | // floating window to count deleted rows |
162 | std::vector<bool> m_deleted_rows_window; |
163 | uint64_t m_rows, m_window_pos, m_deleted_rows, m_max_deleted_rows; |
164 | uint64_t m_file_size; |
165 | Rdb_compact_params m_params; |
166 | Rdb_tbl_card_coll m_cardinality_collector; |
167 | }; |
168 | |
169 | class Rdb_tbl_prop_coll_factory |
170 | : public rocksdb::TablePropertiesCollectorFactory { |
171 | public: |
172 | Rdb_tbl_prop_coll_factory(const Rdb_tbl_prop_coll_factory &) = delete; |
173 | Rdb_tbl_prop_coll_factory & |
174 | operator=(const Rdb_tbl_prop_coll_factory &) = delete; |
175 | |
176 | explicit Rdb_tbl_prop_coll_factory(Rdb_ddl_manager *ddl_manager) |
177 | : m_ddl_manager(ddl_manager) {} |
178 | |
179 | /* |
180 | Override parent class's virtual methods of interest. |
181 | */ |
182 | |
183 | virtual rocksdb::TablePropertiesCollector *CreateTablePropertiesCollector( |
184 | rocksdb::TablePropertiesCollectorFactory::Context context) override { |
185 | return new Rdb_tbl_prop_coll(m_ddl_manager, m_params, |
186 | context.column_family_id, |
187 | m_table_stats_sampling_pct); |
188 | } |
189 | |
190 | virtual const char *Name() const override { |
191 | return "Rdb_tbl_prop_coll_factory" ; |
192 | } |
193 | |
194 | public: |
195 | void SetCompactionParams(const Rdb_compact_params ¶ms) { |
196 | m_params = params; |
197 | } |
198 | |
199 | void SetTableStatsSamplingPct(const uint8_t &table_stats_sampling_pct) { |
200 | m_table_stats_sampling_pct = table_stats_sampling_pct; |
201 | } |
202 | |
203 | private: |
204 | Rdb_ddl_manager *const m_ddl_manager; |
205 | Rdb_compact_params m_params; |
206 | uint8_t m_table_stats_sampling_pct; |
207 | }; |
208 | |
209 | } // namespace myrocks |
210 | |