Commit 211e3022 authored by Vicențiu Ciorbaru's avatar Vicențiu Ciorbaru

WIP rnd used from mysys

parent 29f77d41
......@@ -292,6 +292,9 @@ extern int mi_extra(struct st_myisam_info *file,
extern int mi_reset(struct st_myisam_info *file);
extern ha_rows mi_records_in_range(MI_INFO *info,int inx,
key_range *min_key, key_range *max_key);
extern int mi_random_sample_init(MYSQL_THD thd, MI_INFO *info, ha_rows estimate_rows_read);
extern int mi_random_sample(MI_INFO *info, uchar *buf);
extern int mi_random_sample_end(MI_INFO *info);
extern int mi_log(int activate_log);
extern int mi_is_changed(struct st_myisam_info *info);
extern int mi_delete_all_rows(struct st_myisam_info *info);
......
......@@ -2940,7 +2940,7 @@ class handler :public Sql_alloc
/** Length of ref (1-8 or the clustered key length) */
uint ref_length;
FT_INFO *ft_handler;
enum init_stat { NONE=0, INDEX, RND };
enum init_stat { NONE=0, INDEX, RND, RANDOM };
init_stat inited, pre_inited;
const COND *pushed_cond;
......@@ -3105,6 +3105,27 @@ class handler :public Sql_alloc
virtual int prepare_range_scan(const key_range *start_key, const key_range *end_key)
{ return 0; }
virtual int ha_random_sample_init(THD *thd, ha_rows estimate_rows_read)
__attribute__((warn_unused_result))
{
DBUG_ENTER("ha_random_sample_init");
inited= RANDOM;
DBUG_RETURN(random_sample_init(thd, estimate_rows_read));
}
virtual int ha_random_sample(uchar *buf)
__attribute__((warn_unused_result))
{
DBUG_ENTER("ha_random_sample");
DBUG_ASSERT(inited == RANDOM);
DBUG_RETURN(random_sample(buf));
}
virtual int ha_random_sample_end() __attribute__((warn_unused_result))
{
DBUG_ENTER("ha_random_sample_end");
inited= NONE;
DBUG_RETURN(random_sample_end());
}
int ha_rnd_init(bool scan) __attribute__ ((warn_unused_result))
{
DBUG_EXECUTE_IF("ha_rnd_init_fail", return HA_ERR_TABLE_DEF_CHANGED;);
......@@ -4418,6 +4439,12 @@ class handler :public Sql_alloc
/* Note: ha_index_read_idx_map() may bypass index_init() */
virtual int index_init(uint idx, bool sorted) { return 0; }
virtual int index_end() { return 0; }
virtual int random_sample_init(MYSQL_THD thd, ha_rows estimate_rows_read) { return 0; } ;
virtual int random_sample(uchar *buf)
{
return HA_ERR_WRONG_COMMAND;
}
virtual int random_sample_end() { return 0; };
/**
rnd_init() can be called two times without rnd_end() in between
(it only makes sense if scan=1).
......
......@@ -2743,6 +2743,11 @@ int collect_statistics_for_table(THD *thd, TABLE *table)
restore_record(table, s->default_values);
rc= file->ha_random_sample_init(thd, 100);
rc= file->ha_random_sample(table->record[0]);
rc= file->ha_random_sample_end();
/* Perform a full table scan to collect statistics on 'table's columns */
if (!(rc= file->ha_rnd_init(TRUE)))
{
......
......@@ -2722,4 +2722,22 @@ my_bool ha_myisam::register_query_cache_table(THD *thd, const char *table_name,
/* It is ok to try to cache current statement. */
DBUG_RETURN(TRUE);
}
int ha_myisam::random_sample_init(MYSQL_THD thd, ha_rows estimate_rows_read)
{
DBUG_ENTER("ha_myisam::random_sample_init");
DBUG_RETURN(mi_random_sample_init(thd, file, estimate_rows_read));
}
int ha_myisam::random_sample(uchar *buf)
{
DBUG_ENTER("ha_myisam::random_sample");
DBUG_RETURN(mi_random_sample(file, buf));
}
int ha_myisam::random_sample_end()
{
DBUG_ENTER("ha_myisam::random_sample_end");
DBUG_RETURN(mi_random_sample_end(file));
}
#endif
......@@ -97,6 +97,9 @@ class ha_myisam: public handler
table->record[0]);
}
int ft_read(uchar *buf);
int random_sample_init(MYSQL_THD thd, ha_rows estimate_rows_read) override;
int random_sample(uchar *buf) override;
int random_sample_end() override;
int rnd_init(bool scan);
int rnd_next(uchar *buf);
int rnd_pos(uchar * buf, uchar *pos);
......
......@@ -214,7 +214,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
last_use_keyseg Store pointer to the keyseg after the last used one
*/
uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, const uchar *old,
key_part_map keypart_map, HA_KEYSEG **last_used_keyseg)
{
uchar *start_key=key;
......
......@@ -285,3 +285,173 @@ static uint _mi_keynr(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
*ret_max_key=max_key;
return(keynr);
}
static int _mi_read_sample_static_record(MI_INFO *info, uchar *buf)
{
DBUG_ENTER("_mi_read_sample_static_record");
DBUG_ASSERT(info->s->read_rnd == _mi_read_rnd_static_record);
DBUG_RETURN(0);
}
static int _mi_read_sample_bernoulli(MI_INFO *info, uchar *buf)
{
double select_probability;
int res;
DBUG_ENTER("_mi_get_sample_bernoulli");
if (fast_mi_readinfo(info))
DBUG_RETURN(-1);
if (!info->state->records)
DBUG_RETURN(HA_ERR_END_OF_FILE);
select_probability= (double) info->sampling_state.estimate_rows_read /
info->state->records;
do
{
res= mi_scan(info, buf);
/* Restart scan if we reached the end. */
if (res == HA_ERR_END_OF_FILE)
{
if ((res= mi_scan_init(info)))
DBUG_RETURN(res);
/* Second failure, abort. */
if ((res= mi_scan(info, buf)))
DBUG_RETURN(res);
}
} while (my_rnd_ssl(&info->sampling_state.rand) < select_probability);
fast_mi_writeinfo(info);
DBUG_RETURN(0);
}
int mi_random_sample_init(MYSQL_THD thd, MI_INFO *info,
ha_rows estimate_rows_read)
{
int res= 0;
DBUG_ENTER("mi_random_sample_init");
struct st_sampling_state *ss= &info->sampling_state;
ss->initialised= TRUE;
ss->estimate_rows_read= estimate_rows_read;
ss->thd= thd;
ss->rand.max_value= 1;
my_rnd_init(&ss->rand, 42, 32);
/* Fastest possible case, equal sized records. */
if (!(info->s->options & (HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD)))
{
info->sampling_state.read_sample= _mi_read_sample_static_record;
}
/* Fallback revert to simple scan. */
info->sampling_state.read_sample= _mi_read_sample_bernoulli;
mi_scan_init(info);
DBUG_RETURN(res);
}
int mi_random_sample(MI_INFO *info, uchar *buf)
{
int nod_flag;
int inx;
MI_KEYDEF *keyinfo;
my_off_t pos;
uchar *page;
uchar *key_buff;
uint key_len;
DBUG_ENTER("mi_random_sample");
DBUG_ASSERT(info->sampling_state.initialised == TRUE);
DBUG_RETURN(info->sampling_state.read_sample(info, buf));
/* TODO(cvicentiu): Use first index for now. */
if ((inx= _mi_check_index(info, 0)) < 0)
goto err;
if (fast_mi_readinfo(info))
goto err;
/* Don't clear if database-changed */
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
if (info->s->concurrent_insert)
mysql_rwlock_rdlock(&info->s->key_root_lock[inx]);
/* TODO(cvicentiu): For now, only support BTREE random sampling. */
if (info->s->keyinfo[inx].key_alg != HA_KEY_ALG_BTREE)
goto err;
keyinfo= &info->s->keyinfo[inx];
pos= info->s->state.key_root[inx];
do
{
if (!_mi_fetch_keypage(info, keyinfo, pos, DFLT_INIT_HITS, info->buff, 0))
{
info->lastpos= HA_OFFSET_ERROR;
goto err;
}
nod_flag= mi_test_if_nod(info->buff);
page= info->buff + 2 + nod_flag;
info->lastkey_length= keyinfo->get_key(keyinfo, nod_flag, &page,
info->lastkey);
info->lastpos= _mi_dpos(info, nod_flag, page);
info->read_record(info, info->lastpos, buf);
} while ((pos= _mi_kpos(nod_flag, page)) != HA_OFFSET_ERROR);
/*
do
{
if (!_mi_fetch_keypage(info, keyinfo, pos, DFLT_INIT_HITS, info->buff, 0))
{
info->lastpos= HA_OFFSET_ERROR;
DBUG_RETURN(HA_POS_ERROR);
}
nod_flag= mi_test_if_nod(info->buff);
page= info->buff + 2 + nod_flag;
} while ((pos= _mi_kpos(nod_flag, page)) != HA_OFFSET_ERROR);
if (!(info->lastkey_length= keyinfo->get_key(keyinfo, nod_flag, &page,
info->lastkey)))
DBUG_RETURN(-1);
info->lastpos= _mi_dpos(info, 0, info->lastkey + info->lastkey_length);
*/
info->read_record(info, info->lastpos, buf);
if (info->s->concurrent_insert)
mysql_rwlock_unlock(&info->s->key_root_lock[inx]);
fast_mi_writeinfo(info);
/*
key_buff= info->lastkey + info->s->base.max_key_length;
key_len= _mi_pack_key(info, inx, key_buff, key, keypart_map,
NULL);
*/
/*
if (!(page= _mi_fetch_keypage(info, keyinfo, root_pos, DFLT_INIT_HITS,
info->buff, 1)))
goto err;
*/
/*
flag= keyinfo->bin_search(info, keyinfo, page_buff, key, key_len, nextflag,
&keypos, info->lastkey, &after_key);
*/
DBUG_RETURN(0);
err:
DBUG_PRINT("exit", ("Error: %d", my_errno));
DBUG_RETURN(-1);
}
int mi_random_sample_end(MI_INFO *info)
{
ha_rows res= 0;
DBUG_ENTER("mi_random_sample_end");
info->sampling_state.initialised= TRUE;
DBUG_RETURN(res);
}
......@@ -23,6 +23,7 @@
#include <my_tree.h>
#include <my_pthread.h>
#include <thr_lock.h>
#include <my_rnd.h>
#include <mysql/psi/mysql_file.h>
C_MODE_START
......@@ -39,6 +40,7 @@ typedef struct st_mi_status_info
my_bool uncacheable; /* Active concurrent insert */
} MI_STATUS_INFO;
typedef struct st_mi_state_info
{
struct
......@@ -231,6 +233,21 @@ typedef struct st_mi_isam_share
mysql_rwlock_t mmap_lock;
} MYISAM_SHARE;
struct st_sampling_state
{
my_bool initialised; /* TODO(cvicentiu) delete if not necessary */
MYSQL_THD *thd; /* Used for the random number service. */
struct my_rnd_struct rand;
ha_rows estimate_rows_read; /* How many rows will be sampled. */
int inx; /* If index is used for sampling,
the index number, otherwise -1 */
my_off_t last_record_offset; /* Offset after the last record returned
as sample. */
int(*read_sample) (struct st_myisam_info *, uchar *buf);
};
struct st_myisam_info
{
......@@ -309,6 +326,7 @@ struct st_myisam_info
THR_LOCK_DATA lock;
uchar *rtree_recursion_state; /* For RTREE */
int rtree_recursion_depth;
struct st_sampling_state sampling_state;
};
#define USE_WHOLE_KEY (HA_MAX_KEY_BUFF*2) /* Use whole key in _mi_search() */
......@@ -557,7 +575,7 @@ extern my_off_t _mi_new(MI_INFO *info, MI_KEYDEF *keyinfo, int level);
extern uint _mi_make_key(MI_INFO *info, uint keynr, uchar *key,
const uchar *record, my_off_t filepos);
extern uint _mi_pack_key(MI_INFO *info, uint keynr, uchar *key,
uchar *old, key_part_map keypart_map,
const uchar *old, key_part_map keypart_map,
HA_KEYSEG ** last_used_keyseg);
extern int _mi_read_key_record(MI_INFO *info, my_off_t filepos, uchar *buf);
extern int _mi_read_cache(IO_CACHE *info, uchar *buff, my_off_t pos,
......@@ -704,6 +722,7 @@ int _mi_cmp_static_unique(MI_INFO *info, MI_UNIQUEDEF *def,
const uchar *record, my_off_t pos);
int _mi_cmp_dynamic_unique(MI_INFO *info, MI_UNIQUEDEF *def,
const uchar *record, my_off_t pos);
int _mi_get_sample_static(MI_INFO *info);
int mi_unique_comp(MI_UNIQUEDEF *def, const uchar *a, const uchar *b,
my_bool null_are_equal);
void mi_get_status(void *param, my_bool concurrent_insert);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment