summaryrefslogtreecommitdiff
path: root/sql/partition_info.h
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2018-02-21 15:16:19 +0100
committerSergei Golubchik <serg@mariadb.org>2018-02-23 19:17:48 +0100
commite36c5ec0a50332840c7dcb8e6b08a369ec2a829c (patch)
treeaf84bd00042773cabddb4150748601c53d78b783 /sql/partition_info.h
parent7961bc4b890071f281da88845489cdddc54c289b (diff)
downloadmariadb-git-e36c5ec0a50332840c7dcb8e6b08a369ec2a829c.tar.gz
PARTITION BY SYSTEM_TIME INTERVAL ...
Lots of changes: * calculate the current history partition in ::external_lock(), not in ::write_row() or ::update_row() * remove dynamically collected per-partition row_end stats * no full table scan in open_table_from_share to calculate these stats, no manual MDL/thr_locks in open_table_from_share * no shared stats in TABLE_SHARE = no mutexes or condition waits when calculating current history partition * always compare timestamps, don't convert them to MYSQL_TIME (avoid DST ambiguity, and it's faster too) * correct interval handling, 1 month = 1 month, not 30 * 24 * 3600 seconds * save/restore first partition start time, and count intervals from there * only allow to drop first partitions if INTERVAL * when adding new history partitions, split the data in the last history parition, if it was overflowed * show partition boundaries in INFORMATION_SCHEMA.PARTITIONS
Diffstat (limited to 'sql/partition_info.h')
-rw-r--r--sql/partition_info.h187
1 files changed, 32 insertions, 155 deletions
diff --git a/sql/partition_info.h b/sql/partition_info.h
index 1170aa53e7d..6d2e222ec30 100644
--- a/sql/partition_info.h
+++ b/sql/partition_info.h
@@ -37,40 +37,43 @@ struct st_ddl_log_memory_entry;
struct Vers_part_info : public Sql_alloc
{
Vers_part_info() :
- interval(0),
limit(0),
now_part(NULL),
- hist_part(NULL),
- stat_serial(0)
+ hist_part(NULL)
{
+ interval.type= INTERVAL_LAST;
}
Vers_part_info(Vers_part_info &src) :
interval(src.interval),
limit(src.limit),
now_part(NULL),
- hist_part(NULL),
- stat_serial(src.stat_serial)
+ hist_part(NULL)
{
}
- bool initialized(bool fully= true)
+ bool initialized()
{
if (now_part)
{
DBUG_ASSERT(now_part->id != UINT_MAX32);
DBUG_ASSERT(now_part->type() == partition_element::CURRENT);
- DBUG_ASSERT(!fully || (bool) hist_part);
- DBUG_ASSERT(!hist_part || (
- hist_part->id != UINT_MAX32 &&
- hist_part->type() == partition_element::HISTORY));
+ if (hist_part)
+ {
+ DBUG_ASSERT(hist_part->id != UINT_MAX32);
+ DBUG_ASSERT(hist_part->type() == partition_element::HISTORY);
+ }
return true;
}
return false;
}
- my_time_t interval;
+ struct {
+ my_time_t start;
+ INTERVAL step;
+ enum interval_type type;
+ bool is_set() { return type < INTERVAL_LAST; }
+ } interval;
ulonglong limit;
partition_element *now_part;
partition_element *hist_part;
- ulonglong stat_serial;
};
class partition_info : public Sql_alloc
@@ -391,38 +394,25 @@ public:
bool has_unique_name(partition_element *element);
bool vers_init_info(THD *thd);
- bool vers_set_interval(const INTERVAL &i);
- bool vers_set_limit(ulonglong limit);
- partition_element* vers_part_rotate(THD *thd);
- bool vers_set_expression(THD *thd, partition_element *el, MYSQL_TIME &t);
- bool vers_setup_expression(THD *thd, uint32 alter_add= 0); /* Stage 1. */
- bool vers_setup_stats(THD *thd, bool is_create_table_ind); /* Stage 2. */
- bool vers_scan_min_max(THD *thd, partition_element *part);
- void vers_update_col_vals(THD *thd, partition_element *el0, partition_element *el1);
-
- partition_element *vers_hist_part()
+ bool vers_set_interval(Item *item, interval_type int_type, my_time_t start)
{
- DBUG_ASSERT(table && table->s);
- DBUG_ASSERT(vers_info && vers_info->initialized());
- DBUG_ASSERT(table->s->hist_part_id != UINT_MAX32);
- if (table->s->hist_part_id == vers_info->hist_part->id)
- return vers_info->hist_part;
-
- List_iterator<partition_element> it(partitions);
- partition_element *el;
- while ((el= it++))
- {
- DBUG_ASSERT(el->type() != partition_element::CONVENTIONAL);
- if (el->type() == partition_element::HISTORY &&
- el->id == table->s->hist_part_id)
- {
- vers_info->hist_part= el;
- return vers_info->hist_part;
- }
- }
- DBUG_ASSERT(0);
- return NULL;
+ DBUG_ASSERT(part_type == VERSIONING_PARTITION);
+ vers_info->interval.type= int_type;
+ vers_info->interval.start= start;
+ return get_interval_value(item, int_type, &vers_info->interval.step) ||
+ vers_info->interval.step.neg || vers_info->interval.step.second_part ||
+ !(vers_info->interval.step.year || vers_info->interval.step.month ||
+ vers_info->interval.step.day || vers_info->interval.step.hour ||
+ vers_info->interval.step.minute || vers_info->interval.step.second);
}
+ bool vers_set_limit(ulonglong limit)
+ {
+ DBUG_ASSERT(part_type == VERSIONING_PARTITION);
+ vers_info->limit= limit;
+ return !limit;
+ }
+ void vers_set_hist_part(THD *thd);
+ bool vers_setup_expression(THD *thd, uint32 alter_add= 0); /* Stage 1. */
partition_element *get_partition(uint part_id)
{
List_iterator<partition_element> it(partitions);
@@ -434,120 +424,7 @@ public:
}
return NULL;
}
- bool vers_limit_exceed(partition_element *part= NULL)
- {
- DBUG_ASSERT(vers_info);
- if (!vers_info->limit)
- return false;
- if (!part)
- {
- DBUG_ASSERT(vers_info->initialized());
- part= vers_hist_part();
- }
- // TODO: cache thread-shared part_recs and increment on INSERT
- return table->file->part_records(part) >= vers_info->limit;
- }
- Vers_min_max_stats& vers_stat_trx(stat_trx_field fld, uint32 part_element_id)
- {
- DBUG_ASSERT(table && table->s && table->s->stat_trx);
- Vers_min_max_stats* res= table->s->stat_trx[part_element_id * num_columns + fld];
- DBUG_ASSERT(res);
- return *res;
- }
- Vers_min_max_stats& vers_stat_trx(stat_trx_field fld, partition_element *part)
- {
- DBUG_ASSERT(part);
- return vers_stat_trx(fld, part->id);
- }
- bool vers_interval_exceed(my_time_t max_time, partition_element *part= NULL)
- {
- DBUG_ASSERT(vers_info);
- if (!vers_info->interval)
- return false;
- if (!part)
- {
- DBUG_ASSERT(vers_info->initialized());
- part= vers_hist_part();
- }
- my_time_t min_time= vers_stat_trx(STAT_TRX_END, part).min_time();
- return max_time - min_time > vers_info->interval;
- }
- bool vers_interval_exceed(partition_element *part)
- {
- return vers_interval_exceed(vers_stat_trx(STAT_TRX_END, part).max_time(), part);
- }
- bool vers_interval_exceed()
- {
- return vers_interval_exceed(vers_hist_part());
- }
bool vers_trx_id_to_ts(THD *thd, Field *in_trx_id, Field_timestamp &out_ts);
- void vers_update_stats(THD *thd, partition_element *el)
- {
- DBUG_ASSERT(vers_info && vers_info->initialized());
- DBUG_ASSERT(table && table->s);
- DBUG_ASSERT(el && el->type() == partition_element::HISTORY);
- bool updated;
- mysql_rwlock_wrlock(&table->s->LOCK_stat_serial);
- el->empty= false;
- if (table->versioned(VERS_TRX_ID))
- {
- // transaction is not yet pushed to VTQ, so we use now-time
- my_time_t end_ts= my_time_t(0);
-
- uchar buf[8];
- Field_timestampf fld(buf, NULL, 0, Field::NONE, &table->vers_end_field()->field_name, NULL, 6);
- fld.store_TIME(end_ts, 0);
- updated=
- vers_stat_trx(STAT_TRX_END, el->id).update(&fld);
- }
- else
- {
- updated=
- vers_stat_trx(STAT_TRX_END, el->id).update(table->vers_end_field());
- }
- if (updated)
- table->s->stat_serial++;
- mysql_rwlock_unlock(&table->s->LOCK_stat_serial);
- if (updated)
- {
- vers_update_col_vals(thd,
- el->id > 0 ? get_partition(el->id - 1) : NULL,
- el);
- }
- }
- void vers_update_stats(THD *thd, uint part_id)
- {
- DBUG_ASSERT(vers_info && vers_info->initialized());
- uint lpart_id= num_subparts ? part_id / num_subparts : part_id;
- if (lpart_id < vers_info->now_part->id)
- vers_update_stats(thd, get_partition(lpart_id));
- }
- bool vers_update_range_constants(THD *thd)
- {
- DBUG_ASSERT(vers_info && vers_info->initialized());
- DBUG_ASSERT(table && table->s);
-
- mysql_rwlock_rdlock(&table->s->LOCK_stat_serial);
- if (vers_info->stat_serial == table->s->stat_serial)
- {
- mysql_rwlock_unlock(&table->s->LOCK_stat_serial);
- return false;
- }
-
- bool result= false;
- for (uint i= 0; i < num_columns; ++i)
- {
- Field *f= part_field_array[i];
- bitmap_set_bit(f->table->write_set, f->field_index);
- }
- MEM_ROOT *old_root= thd->mem_root;
- thd->mem_root= &table->mem_root;
- //result= check_range_constants(thd, false);
- thd->mem_root= old_root;
- vers_info->stat_serial= table->s->stat_serial;
- mysql_rwlock_unlock(&table->s->LOCK_stat_serial);
- return result;
- }
};
uint32 get_next_partition_id_range(struct st_partition_iter* part_iter);