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 std::atomic<uint64_t> rocksdb_additional_compaction_triggers;
42 extern my_bool rocksdb_compaction_sequential_deletes_count_sd;
43 
44 struct Rdb_compact_params {
45   uint64_t m_deletes, m_window, m_file_size;
46 };
47 
48 struct Rdb_index_stats {
49   enum {
50     INDEX_STATS_VERSION_INITIAL = 1,
51     INDEX_STATS_VERSION_ENTRY_TYPES = 2,
52   };
53   GL_INDEX_ID m_gl_index_id;
54   int64_t m_data_size, m_rows, m_actual_disk_size;
55   int64_t m_entry_deletes, m_entry_single_deletes;
56   int64_t m_entry_merges, m_entry_others;
57   std::vector<int64_t> m_distinct_keys_per_prefix;
58   std::string m_name;  // name is not persisted
59 
60   static std::string materialize(const std::vector<Rdb_index_stats> &stats);
61   static int unmaterialize(const std::string &s,
62                            std::vector<Rdb_index_stats> *const ret);
63 
Rdb_index_statsRdb_index_stats64   Rdb_index_stats() : Rdb_index_stats({0, 0}) {}
Rdb_index_statsRdb_index_stats65   explicit Rdb_index_stats(GL_INDEX_ID gl_index_id)
66       : m_gl_index_id(gl_index_id),
67         m_data_size(0),
68         m_rows(0),
69         m_actual_disk_size(0),
70         m_entry_deletes(0),
71         m_entry_single_deletes(0),
72         m_entry_merges(0),
73         m_entry_others(0) {}
74 
75   void merge(const Rdb_index_stats &s, const bool increment = true,
76              const int64_t estimated_data_len = 0);
77 
78   void adjust_cardinality(double adjustment_factor);
79 
80   void reset_cardinality();
81 };
82 
83 struct Rdb_table_stats {
84   // TODO: With TTL rows can be removed without a decrement in
85   // m_stat_n_rows. We should take TTL into consideration later.
86   uint64 m_stat_n_rows;
87   uint64 m_stat_modified_counter;
88   time_t m_last_recalc;
89 
Rdb_table_statsRdb_table_stats90   Rdb_table_stats()
91       : m_stat_n_rows(0), m_stat_modified_counter(0), m_last_recalc(0) {}
92 
Rdb_table_statsRdb_table_stats93   explicit Rdb_table_stats(uint64 rows, uint64 modified_counter,
94                            time_t last_recalc)
95       : m_stat_n_rows(rows),
96         m_stat_modified_counter(modified_counter),
97         m_last_recalc(last_recalc) {}
98 
setRdb_table_stats99   void set(uint64 rows, uint64 modified_counter, time_t last_recalc) {
100     m_stat_n_rows = rows;
101     m_stat_modified_counter = modified_counter;
102     m_last_recalc = last_recalc;
103   }
104 };
105 
106 // The helper class to calculate index cardinality
107 class Rdb_tbl_card_coll {
108  public:
109   explicit Rdb_tbl_card_coll(const uint8_t table_stats_sampling_pct);
110 
111  public:
112   void ProcessKey(const rocksdb::Slice &key, const Rdb_key_def *keydef,
113                   Rdb_index_stats *stats);
114   /*
115    * Resets the state of the collector to start calculating statistics for a
116    * next index.
117    */
118   void Reset();
119 
120   /*
121    * Cardinality statistics might be calculated using some sampling strategy.
122    * This method adjusts gathered statistics according to the sampling
123    * strategy used. Note that adjusted cardinality value is just an estimate
124    * and can return a value exeeding number of rows in a table, so the
125    * returned value should be capped by row count before using it by
126    * an optrimizer or displaying it to a clent.
127    */
128   void AdjustStats(Rdb_index_stats *stats);
129   void SetCardinality(Rdb_index_stats *stat);
130 
131  private:
132   bool ShouldCollectStats();
133   bool IsSamplingDisabled() const;
134 
135  private:
136   std::string m_last_key;
137   uint8_t m_table_stats_sampling_pct;
138   unsigned int m_seed;
139 };
140 
141 class Rdb_tbl_prop_coll : public rocksdb::TablePropertiesCollector {
142  public:
143   Rdb_tbl_prop_coll(Rdb_ddl_manager *const ddl_manager,
144                     const Rdb_compact_params &params, const uint32_t cf_id,
145                     const uint8_t table_stats_sampling_pct);
146 
147   /*
148     Override parent class's virtual methods of interest.
149   */
150 
151   virtual rocksdb::Status AddUserKey(const rocksdb::Slice &key,
152                                      const rocksdb::Slice &value,
153                                      rocksdb::EntryType type,
154                                      rocksdb::SequenceNumber seq,
155                                      uint64_t file_size) override;
156 
157   virtual rocksdb::Status Finish(
158       rocksdb::UserCollectedProperties *properties) override;
159 
Name()160   virtual const char *Name() const override { return "Rdb_tbl_prop_coll"; }
161 
162   rocksdb::UserCollectedProperties GetReadableProperties() const override;
163 
164   bool NeedCompact() const override;
165 
166  public:
GetMaxDeletedRows()167   uint64_t GetMaxDeletedRows() const { return m_max_deleted_rows; }
168 
169   static void read_stats_from_tbl_props(
170       const std::shared_ptr<const rocksdb::TableProperties> &table_props,
171       std::vector<Rdb_index_stats> *out_stats_vector);
172 
173  private:
174   static std::string GetReadableStats(const Rdb_index_stats &it);
175   bool FilledWithDeletions() const;
176   bool ShouldCollectStats();
177   void CollectStatsForRow(const rocksdb::Slice &key,
178                           const rocksdb::Slice &value,
179                           const rocksdb::EntryType &type,
180                           const uint64_t file_size);
181   Rdb_index_stats *AccessStats(const rocksdb::Slice &key);
182   void AdjustDeletedRows(rocksdb::EntryType type);
183 
184  private:
185   uint32_t m_cf_id;
186   std::shared_ptr<const Rdb_key_def> m_keydef;
187   Rdb_ddl_manager *m_ddl_manager;
188   std::vector<Rdb_index_stats> m_stats;
189   Rdb_index_stats *m_last_stats;
190   static const char *INDEXSTATS_KEY;
191 
192   // last added key
193   std::string m_last_key;
194 
195   // floating window to count deleted rows
196   std::vector<bool> m_deleted_rows_window;
197   uint64_t m_window_pos, m_deleted_rows, m_max_deleted_rows;
198   uint64_t m_total_puts, m_total_merges;
199   uint64_t m_total_deletes, m_total_singledeletes, m_total_others;
200   uint64_t m_file_size;
201   Rdb_compact_params m_params;
202   Rdb_tbl_card_coll m_cardinality_collector;
203   bool m_recorded;
204 };
205 
206 class Rdb_tbl_prop_coll_factory
207     : public rocksdb::TablePropertiesCollectorFactory {
208  public:
209   Rdb_tbl_prop_coll_factory(const Rdb_tbl_prop_coll_factory &) = delete;
210   Rdb_tbl_prop_coll_factory &operator=(const Rdb_tbl_prop_coll_factory &) =
211       delete;
212 
Rdb_tbl_prop_coll_factory(Rdb_ddl_manager * ddl_manager)213   explicit Rdb_tbl_prop_coll_factory(Rdb_ddl_manager *ddl_manager)
214       : m_ddl_manager(ddl_manager) {}
215 
216   /*
217     Override parent class's virtual methods of interest.
218   */
219 
CreateTablePropertiesCollector(rocksdb::TablePropertiesCollectorFactory::Context context)220   virtual rocksdb::TablePropertiesCollector *CreateTablePropertiesCollector(
221       rocksdb::TablePropertiesCollectorFactory::Context context) override {
222     return new Rdb_tbl_prop_coll(m_ddl_manager, m_params,
223                                  context.column_family_id,
224                                  m_table_stats_sampling_pct);
225   }
226 
Name()227   virtual const char *Name() const override {
228     return "Rdb_tbl_prop_coll_factory";
229   }
230 
231  public:
SetCompactionParams(const Rdb_compact_params & params)232   void SetCompactionParams(const Rdb_compact_params &params) {
233     m_params = params;
234   }
235 
SetTableStatsSamplingPct(const uint8_t table_stats_sampling_pct)236   void SetTableStatsSamplingPct(const uint8_t table_stats_sampling_pct) {
237     m_table_stats_sampling_pct = table_stats_sampling_pct;
238   }
239 
240  private:
241   Rdb_ddl_manager *const m_ddl_manager;
242   Rdb_compact_params m_params;
243   uint8_t m_table_stats_sampling_pct;
244 };
245 
246 }  // namespace myrocks
247