Commit f547f276 authored by igor@rurik.mysql.com's avatar igor@rurik.mysql.com

Many files:

  New feature: preload indexes into key cache.
mi_preload.c:
  new file
Many files:
  Added preload statement.
parent 7009100c
...@@ -123,7 +123,8 @@ enum ha_extra_function { ...@@ -123,7 +123,8 @@ enum ha_extra_function {
HA_EXTRA_NO_IGNORE_DUP_KEY, HA_EXTRA_NO_IGNORE_DUP_KEY,
HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE, /* Cursor will not be used for update */ HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE, /* Cursor will not be used for update */
HA_EXTRA_PREPARE_FOR_DELETE, HA_EXTRA_PREPARE_FOR_DELETE,
HA_EXTRA_PREPARE_FOR_UPDATE /* Remove read cache if problems */ HA_EXTRA_PREPARE_FOR_UPDATE, /* Remove read cache if problems */
HA_EXTRA_PRELOAD_BUFFER_SIZE /* Set buffer size for preloading */
}; };
/* The following is parameter to ha_panic() */ /* The following is parameter to ha_panic() */
...@@ -255,6 +256,7 @@ enum ha_base_keytype { ...@@ -255,6 +256,7 @@ enum ha_base_keytype {
#define HA_ERR_CANNOT_ADD_FOREIGN 150 /* Cannot add a foreign key constr. */ #define HA_ERR_CANNOT_ADD_FOREIGN 150 /* Cannot add a foreign key constr. */
#define HA_ERR_NO_REFERENCED_ROW 151 /* Cannot add a child row */ #define HA_ERR_NO_REFERENCED_ROW 151 /* Cannot add a child row */
#define HA_ERR_ROW_IS_REFERENCED 152 /* Cannot delete a parent row */ #define HA_ERR_ROW_IS_REFERENCED 152 /* Cannot delete a parent row */
#define HA_ERR_NON_UNIQUE_BLOCK_SIZE 153 /* Non unique key block size */
/* Other constants */ /* Other constants */
......
...@@ -644,6 +644,8 @@ extern int init_key_cache(ulong use_mem); ...@@ -644,6 +644,8 @@ extern int init_key_cache(ulong use_mem);
extern int resize_key_cache(ulong use_mem); extern int resize_key_cache(ulong use_mem);
extern byte *key_cache_read(File file,my_off_t filepos,byte* buff,uint length, extern byte *key_cache_read(File file,my_off_t filepos,byte* buff,uint length,
uint block_length,int return_buffer); uint block_length,int return_buffer);
extern int key_cache_insert(File file, my_off_t filepos,
byte *buff, uint length);
extern int key_cache_write(File file,my_off_t filepos,byte* buff,uint length, extern int key_cache_write(File file,my_off_t filepos,byte* buff,uint length,
uint block_length,int force_write); uint block_length,int force_write);
extern int flush_key_blocks(int file, enum flush_type type); extern int flush_key_blocks(int file, enum flush_type type);
......
...@@ -410,6 +410,7 @@ my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows, ulonglong key_map, ...@@ -410,6 +410,7 @@ my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows, ulonglong key_map,
int mi_init_bulk_insert(MI_INFO *info, ulong cache_size, ha_rows rows); int mi_init_bulk_insert(MI_INFO *info, ulong cache_size, ha_rows rows);
void mi_flush_bulk_insert(MI_INFO *info, uint inx); void mi_flush_bulk_insert(MI_INFO *info, uint inx);
void mi_end_bulk_insert(MI_INFO *info); void mi_end_bulk_insert(MI_INFO *info);
int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves);
#ifdef __cplusplus #ifdef __cplusplus
} }
......
...@@ -47,6 +47,7 @@ libmyisam_a_SOURCES = mi_open.c mi_extra.c mi_info.c mi_rkey.c \ ...@@ -47,6 +47,7 @@ libmyisam_a_SOURCES = mi_open.c mi_extra.c mi_info.c mi_rkey.c \
mi_range.c mi_dbug.c mi_checksum.c mi_log.c \ mi_range.c mi_dbug.c mi_checksum.c mi_log.c \
mi_changed.c mi_static.c mi_delete_all.c \ mi_changed.c mi_static.c mi_delete_all.c \
mi_delete_table.c mi_rename.c mi_check.c \ mi_delete_table.c mi_rename.c mi_check.c \
mi_preload.c \
ft_parser.c ft_stopwords.c ft_static.c \ ft_parser.c ft_stopwords.c ft_static.c \
ft_update.c ft_boolean_search.c ft_nlq_search.c sort.c \ ft_update.c ft_boolean_search.c ft_nlq_search.c sort.c \
rt_index.c rt_key.c rt_mbr.c rt_split.c sp_key.c rt_index.c rt_key.c rt_mbr.c rt_split.c sp_key.c
......
...@@ -367,6 +367,9 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) ...@@ -367,6 +367,9 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
if (!share->state.header.uniques) if (!share->state.header.uniques)
info->opt_flag|= OPT_NO_ROWS; info->opt_flag|= OPT_NO_ROWS;
break; break;
case HA_EXTRA_PRELOAD_BUFFER_SIZE:
info->preload_buff_size= *((ulong *) extra_arg);
break;
case HA_EXTRA_KEY_CACHE: case HA_EXTRA_KEY_CACHE:
case HA_EXTRA_NO_KEY_CACHE: case HA_EXTRA_NO_KEY_CACHE:
default: default:
......
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
Preload indexes into key cache
*/
#include "myisamdef.h"
/*
Preload pages of the index file for a table into the key cache
SYNOPSIS
mi_preload()
info open table
map map of indexes to preload into key cache
ignore_leaves only non-leaves pages are to be preloaded
RETURN VALUE
0 if a success. error code - otherwise.
NOTES.
At present pages for all indexes are preloaded.
In future only pages for indexes specified in the key_map parameter
of the table will be preloaded.
*/
int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves)
{
uint i;
uint length;
uint block_length= 0;
uchar *buff= NULL;
MYISAM_SHARE* share= info->s;
uint keys= share->state.header.keys;
MI_KEYDEF *keyinfo= share->keyinfo;
my_off_t key_file_length= share->state.state.key_file_length;
my_off_t pos= share->base.keystart;
if (!keys || !key_map || key_file_length == pos)
return 0;
block_length= keyinfo[0].block_length;
if (!key_map)
return 0;
/* Check whether all indexes use the same block size */
for (i= 1 ; i < keys ; i++)
{
if (keyinfo[i].block_length != block_length)
return (my_errno= HA_ERR_NON_UNIQUE_BLOCK_SIZE);
}
length= info->preload_buff_size/block_length * block_length;
set_if_bigger(length, block_length);
if (!(buff= (uchar *) my_malloc(length, MYF(MY_WME))))
return (my_errno= HA_ERR_OUT_OF_MEM);
if (flush_key_blocks(share->kfile, FLUSH_RELEASE))
goto err;
do
{
/* Read the next block of index file into the preload buffer */
set_if_smaller(length, key_file_length-pos);
if (my_pread(share->kfile, (byte*) buff, length, pos, MYF(MY_FAE)))
goto err;
if (ignore_leaves)
{
uchar *end= buff+length;
do
{
if (mi_test_if_nod(buff))
{
if (key_cache_insert(share->kfile, pos, (byte*) buff, block_length))
goto err;
}
pos+= block_length;
}
while ((buff+= block_length) != end);
buff= end-length;
}
else
{
if (key_cache_insert(share->kfile, pos, (byte*) buff, length))
goto err;
pos+= length;
}
}
while (pos != key_file_length);
my_free(buff, MYF(0));
return 0;
err:
my_free(buff, MYF(MY_ALLOW_ZERO_PTR));
return (my_errno= errno);
}
...@@ -262,6 +262,7 @@ struct st_myisam_info { ...@@ -262,6 +262,7 @@ struct st_myisam_info {
int save_lastinx; int save_lastinx;
LIST open_list; LIST open_list;
IO_CACHE rec_cache; /* When cacheing records */ IO_CACHE rec_cache; /* When cacheing records */
uint preload_buff_size; /* When preloading indexes */
myf lock_wait; /* is 0 or MY_DONT_WAIT */ myf lock_wait; /* is 0 or MY_DONT_WAIT */
my_bool was_locked; /* Was locked in panic */ my_bool was_locked; /* Was locked in panic */
my_bool quick_mode; my_bool quick_mode;
......
...@@ -1258,6 +1258,86 @@ byte *key_cache_read(File file, my_off_t filepos, byte *buff, uint length, ...@@ -1258,6 +1258,86 @@ byte *key_cache_read(File file, my_off_t filepos, byte *buff, uint length,
} }
/*
Insert a block of file data from a buffer into key cache
SYNOPSIS
key_cache_insert()
file file descriptor
filepos file offset of the data from the buffer
buff buffer with data to insert into key cache
length length of the data in the buffer
RETURN VALUE
0 if a success, 1 -otherwise.
*/
int key_cache_insert(File file, my_off_t filepos, byte *buff, uint length)
{
DBUG_ENTER("key_cache_insert");
DBUG_PRINT("enter", ("file %u, filepos %lu, length %u",
(uint) file,(ulong) filepos, length));
if (my_disk_blocks > 0)
{
/* Key cache is used */
reg1 BLOCK_LINK *block;
uint offset= (uint) (filepos & (key_cache_block_size-1));
uint read_length;
int page_st;
/* Read data into key cache from buff in key_cache_block_size increments */
filepos-= offset;
do
{
read_length= length > key_cache_block_size ?
key_cache_block_size : length;
KEYCACHE_DBUG_ASSERT(read_length > 0);
keycache_pthread_mutex_lock(&THR_LOCK_keycache);
my_cache_r_requests++;
block=find_key_block(file, filepos, 0, &page_st);
if (block->status != BLOCK_ERROR && page_st != PAGE_READ)
{
/* The requested page is to be read into the block buffer */
#if !defined(SERIALIZED_READ_FROM_CACHE)
keycache_pthread_mutex_unlock(&THR_LOCK_keycache);
#endif
/* Copy data from buff */
if (!(read_length & 511))
bmove512(block->buffer+offset, buff, read_length);
else
memcpy(block->buffer+offset, buff, (size_t) read_length);
#if !defined(SERIALIZED_READ_FROM_CACHE)
keycache_pthread_mutex_lock(&THR_LOCK_keycache);
#endif
block->status= BLOCK_READ;
block->length= read_length+offset;
}
remove_reader(block);
/*
Link the block into the LRU chain
if it's the last submitted request for the block
*/
unreg_request(block,1);
keycache_pthread_mutex_unlock(&THR_LOCK_keycache);
if (block->status & BLOCK_ERROR)
DBUG_RETURN(1);
buff+=read_length;
filepos+=read_length;
offset=0;
} while ((length-= read_length));
}
DBUG_RETURN(0);
}
/* /*
Write a buffer into disk; Write a buffer into disk;
filepos must be a multiple of 'block_length', but it doesn't filepos must be a multiple of 'block_length', but it doesn't
......
...@@ -674,6 +674,72 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize) ...@@ -674,6 +674,72 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
} }
/*
Preload pages of the index file for a table into the key cache.
*/
int ha_myisam::preload_keys(THD* thd, HA_CHECK_OPT *check_opt)
{
int error;
const char *errmsg;
ulonglong map= ~(ulonglong) 0;
TABLE_LIST *table_list= table->pos_in_table_list;
my_bool ignore_leaves= table_list->ignore_leaves;
DBUG_ENTER("ha_myisam::preload_keys");
/* Check validity of the index references */
if (table_list->use_index)
{
key_map kmap= get_key_map_from_key_list(table, table_list->use_index);
if (kmap == ~(key_map) 0)
{
errmsg= thd->net.last_error;
error= HA_ADMIN_FAILED;
goto err;
}
if (kmap)
map= kmap;
}
mi_extra(file, HA_EXTRA_PRELOAD_BUFFER_SIZE,
(void *) &thd->variables.preload_buff_size);
if ((error= mi_preload(file, map, ignore_leaves)))
{
switch (error) {
case HA_ERR_NON_UNIQUE_BLOCK_SIZE:
errmsg= "Indexes use different block sizes";
break;
case HA_ERR_OUT_OF_MEM:
errmsg= "Failed to allocate buffer";
break;
default:
char buf[ERRMSGSIZE+20];
my_snprintf(buf, ERRMSGSIZE,
"Failed to read from index file (errno: %d)", my_errno);
errmsg= buf;
}
error= HA_ADMIN_FAILED;
goto err;
}
DBUG_RETURN(HA_ADMIN_OK);
err:
{
MI_CHECK param;
myisamchk_init(&param);
param.thd= thd;
param.op_name= (char*)"preload_keys";
param.db_name= table->table_cache_key;
param.table_name= table->table_name;
param.testflag= 0;
mi_check_print_error(&param, errmsg);
DBUG_RETURN(error);
}
}
/* /*
Deactive all not unique index that can be recreated fast Deactive all not unique index that can be recreated fast
......
...@@ -127,6 +127,7 @@ class ha_myisam: public handler ...@@ -127,6 +127,7 @@ class ha_myisam: public handler
int optimize(THD* thd, HA_CHECK_OPT* check_opt); int optimize(THD* thd, HA_CHECK_OPT* check_opt);
int restore(THD* thd, HA_CHECK_OPT* check_opt); int restore(THD* thd, HA_CHECK_OPT* check_opt);
int backup(THD* thd, HA_CHECK_OPT* check_opt); int backup(THD* thd, HA_CHECK_OPT* check_opt);
int preload_keys(THD* thd, HA_CHECK_OPT* check_opt);
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
int dump(THD* thd, int fd); int dump(THD* thd, int fd);
int net_read_dump(NET* net); int net_read_dump(NET* net);
......
...@@ -588,6 +588,11 @@ int handler::analyze(THD* thd, HA_CHECK_OPT* check_opt) ...@@ -588,6 +588,11 @@ int handler::analyze(THD* thd, HA_CHECK_OPT* check_opt)
return HA_ADMIN_NOT_IMPLEMENTED; return HA_ADMIN_NOT_IMPLEMENTED;
} }
int handler::preload_keys(THD* thd, HA_CHECK_OPT* check_opt)
{
return HA_ADMIN_NOT_IMPLEMENTED;
}
/* /*
Read first row (only) from a table Read first row (only) from a table
This is never called for InnoDB or BDB tables, as these table types This is never called for InnoDB or BDB tables, as these table types
......
...@@ -304,6 +304,7 @@ class handler :public Sql_alloc ...@@ -304,6 +304,7 @@ class handler :public Sql_alloc
virtual int optimize(THD* thd,HA_CHECK_OPT* check_opt); virtual int optimize(THD* thd,HA_CHECK_OPT* check_opt);
virtual int analyze(THD* thd, HA_CHECK_OPT* check_opt); virtual int analyze(THD* thd, HA_CHECK_OPT* check_opt);
virtual int backup(THD* thd, HA_CHECK_OPT* check_opt); virtual int backup(THD* thd, HA_CHECK_OPT* check_opt);
virtual int preload_keys(THD* thd, HA_CHECK_OPT* check_opt);
/* /*
restore assumes .frm file must exist, and that generate_table() has been restore assumes .frm file must exist, and that generate_table() has been
called; It will just copy the data file and run repair. called; It will just copy the data file and run repair.
......
...@@ -221,6 +221,7 @@ static SYMBOL symbols[] = { ...@@ -221,6 +221,7 @@ static SYMBOL symbols[] = {
{ "KILL", SYM(KILL_SYM),0,0}, { "KILL", SYM(KILL_SYM),0,0},
{ "LAST", SYM(LAST_SYM),0,0}, { "LAST", SYM(LAST_SYM),0,0},
{ "LEADING", SYM(LEADING),0,0}, { "LEADING", SYM(LEADING),0,0},
{ "LEAVES", SYM(LEAVES),0,0},
{ "LEFT", SYM(LEFT),0,0}, { "LEFT", SYM(LEFT),0,0},
{ "LEVEL", SYM(LEVEL_SYM),0,0}, { "LEVEL", SYM(LEVEL_SYM),0,0},
{ "LIKE", SYM(LIKE),0,0}, { "LIKE", SYM(LIKE),0,0},
...@@ -299,6 +300,7 @@ static SYMBOL symbols[] = { ...@@ -299,6 +300,7 @@ static SYMBOL symbols[] = {
{ "POLYGON", SYM(POLYGON),0,0}, { "POLYGON", SYM(POLYGON),0,0},
{ "PURGE", SYM(PURGE),0,0}, { "PURGE", SYM(PURGE),0,0},
{ "PRECISION", SYM(PRECISION),0,0}, { "PRECISION", SYM(PRECISION),0,0},
{ "PRELOAD", SYM(PRELOAD),0,0},
{ "PREV", SYM(PREV_SYM),0,0}, { "PREV", SYM(PREV_SYM),0,0},
{ "PRIMARY", SYM(PRIMARY_SYM),0,0}, { "PRIMARY", SYM(PRIMARY_SYM),0,0},
{ "PROCEDURE", SYM(PROCEDURE),0,0}, { "PROCEDURE", SYM(PROCEDURE),0,0},
......
...@@ -246,6 +246,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout); ...@@ -246,6 +246,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout);
/* Options to add_table_to_list() */ /* Options to add_table_to_list() */
#define TL_OPTION_UPDATING 1 #define TL_OPTION_UPDATING 1
#define TL_OPTION_FORCE_INDEX 2 #define TL_OPTION_FORCE_INDEX 2
#define TL_OPTION_IGNORE_LEAVES 4
/* Some portable defines */ /* Some portable defines */
...@@ -393,6 +394,8 @@ int mysql_analyze_table(THD* thd, TABLE_LIST* table_list, ...@@ -393,6 +394,8 @@ int mysql_analyze_table(THD* thd, TABLE_LIST* table_list,
HA_CHECK_OPT* check_opt); HA_CHECK_OPT* check_opt);
int mysql_optimize_table(THD* thd, TABLE_LIST* table_list, int mysql_optimize_table(THD* thd, TABLE_LIST* table_list,
HA_CHECK_OPT* check_opt); HA_CHECK_OPT* check_opt);
int mysql_preload_keys(THD* thd, TABLE_LIST* table_list);
bool check_simple_select(); bool check_simple_select();
SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length); SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length);
...@@ -584,6 +587,8 @@ enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND, ...@@ -584,6 +587,8 @@ enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND,
extern const Item **not_found_item; extern const Item **not_found_item;
Item ** find_item_in_list(Item *item, List<Item> &items, uint *counter, Item ** find_item_in_list(Item *item, List<Item> &items, uint *counter,
find_item_error_report_type report_error); find_item_error_report_type report_error);
key_map get_key_map_from_key_list(TABLE *table,
List<String> *index_list);
bool insert_fields(THD *thd,TABLE_LIST *tables, bool insert_fields(THD *thd,TABLE_LIST *tables,
const char *db_name, const char *table_name, const char *db_name, const char *table_name,
List_iterator<Item> *it); List_iterator<Item> *it);
......
...@@ -3464,6 +3464,7 @@ enum options ...@@ -3464,6 +3464,7 @@ enum options
OPT_NET_BUFFER_LENGTH, OPT_NET_RETRY_COUNT, OPT_NET_BUFFER_LENGTH, OPT_NET_RETRY_COUNT,
OPT_NET_READ_TIMEOUT, OPT_NET_WRITE_TIMEOUT, OPT_NET_READ_TIMEOUT, OPT_NET_WRITE_TIMEOUT,
OPT_OPEN_FILES_LIMIT, OPT_OPEN_FILES_LIMIT,
OPT_PRELOAD_BUFFER_SIZE,
OPT_QUERY_CACHE_LIMIT, OPT_QUERY_CACHE_MIN_RES_UNIT, OPT_QUERY_CACHE_SIZE, OPT_QUERY_CACHE_LIMIT, OPT_QUERY_CACHE_MIN_RES_UNIT, OPT_QUERY_CACHE_SIZE,
OPT_QUERY_CACHE_TYPE, OPT_RECORD_BUFFER, OPT_QUERY_CACHE_TYPE, OPT_RECORD_BUFFER,
OPT_RECORD_RND_BUFFER, OPT_RELAY_LOG_SPACE_LIMIT, OPT_RELAY_LOG_PURGE, OPT_RECORD_RND_BUFFER, OPT_RELAY_LOG_SPACE_LIMIT, OPT_RELAY_LOG_PURGE,
...@@ -4244,6 +4245,11 @@ Disable with --skip-isam", ...@@ -4244,6 +4245,11 @@ Disable with --skip-isam",
"If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of files.", "If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of files.",
(gptr*) &open_files_limit, (gptr*) &open_files_limit, 0, GET_ULONG, (gptr*) &open_files_limit, (gptr*) &open_files_limit, 0, GET_ULONG,
REQUIRED_ARG, 0, 0, 65535, 0, 1, 0}, REQUIRED_ARG, 0, 0, 65535, 0, 1, 0},
{"preload_buffer_size", OPT_PRELOAD_BUFFER_SIZE,
"The size of the buffer that is allocated when preloading indexes",
(gptr*) &global_system_variables.preload_buff_size,
(gptr*) &max_system_variables.preload_buff_size, 0, GET_ULONG,
REQUIRED_ARG, 32*1024L, 1024, 1024*1024*1024L, 0, 1, 0},
#ifdef HAVE_QUERY_CACHE #ifdef HAVE_QUERY_CACHE
{"query_cache_limit", OPT_QUERY_CACHE_LIMIT, {"query_cache_limit", OPT_QUERY_CACHE_LIMIT,
"Don't cache results that are bigger than this.", "Don't cache results that are bigger than this.",
......
...@@ -199,6 +199,8 @@ sys_var_thd_ulong sys_net_retry_count("net_retry_count", ...@@ -199,6 +199,8 @@ sys_var_thd_ulong sys_net_retry_count("net_retry_count",
&SV::net_retry_count, &SV::net_retry_count,
fix_net_retry_count); fix_net_retry_count);
sys_var_thd_bool sys_new_mode("new", &SV::new_mode); sys_var_thd_bool sys_new_mode("new", &SV::new_mode);
sys_var_thd_ulong sys_preload_buff_size("preload_buffer_size",
&SV::preload_buff_size);
sys_var_thd_ulong sys_read_buff_size("read_buffer_size", sys_var_thd_ulong sys_read_buff_size("read_buffer_size",
&SV::read_buff_size); &SV::read_buff_size);
sys_var_thd_ulong sys_read_rnd_buff_size("read_rnd_buffer_size", sys_var_thd_ulong sys_read_rnd_buff_size("read_rnd_buffer_size",
...@@ -402,6 +404,7 @@ sys_var *sys_variables[]= ...@@ -402,6 +404,7 @@ sys_var *sys_variables[]=
&sys_net_wait_timeout, &sys_net_wait_timeout,
&sys_net_write_timeout, &sys_net_write_timeout,
&sys_new_mode, &sys_new_mode,
&sys_preload_buff_size,
&sys_pseudo_thread_id, &sys_pseudo_thread_id,
&sys_query_cache_size, &sys_query_cache_size,
#ifdef HAVE_QUERY_CACHE #ifdef HAVE_QUERY_CACHE
...@@ -573,6 +576,7 @@ struct show_var_st init_vars[]= { ...@@ -573,6 +576,7 @@ struct show_var_st init_vars[]= {
{"log_error", (char*) log_error_file, SHOW_CHAR}, {"log_error", (char*) log_error_file, SHOW_CHAR},
{"port", (char*) &mysql_port, SHOW_INT}, {"port", (char*) &mysql_port, SHOW_INT},
{"protocol_version", (char*) &protocol_version, SHOW_INT}, {"protocol_version", (char*) &protocol_version, SHOW_INT},
{sys_preload_buff_size.name, (char*) &sys_preload_buff_size, SHOW_SYS},
{sys_pseudo_thread_id.name, (char*) &sys_pseudo_thread_id, SHOW_SYS}, {sys_pseudo_thread_id.name, (char*) &sys_pseudo_thread_id, SHOW_SYS},
{sys_read_buff_size.name, (char*) &sys_read_buff_size, SHOW_SYS}, {sys_read_buff_size.name, (char*) &sys_read_buff_size, SHOW_SYS},
{sys_read_rnd_buff_size.name,(char*) &sys_read_rnd_buff_size, SHOW_SYS}, {sys_read_rnd_buff_size.name,(char*) &sys_read_rnd_buff_size, SHOW_SYS},
......
...@@ -35,8 +35,6 @@ static int open_unireg_entry(THD *thd,TABLE *entry,const char *db, ...@@ -35,8 +35,6 @@ static int open_unireg_entry(THD *thd,TABLE *entry,const char *db,
const char *name, const char *alias); const char *name, const char *alias);
static void free_cache_entry(TABLE *entry); static void free_cache_entry(TABLE *entry);
static void mysql_rm_tmp_tables(void); static void mysql_rm_tmp_tables(void);
static key_map get_key_map_from_key_list(TABLE *table,
List<String> *index_list);
extern "C" byte *table_cache_key(const byte *record,uint *length, extern "C" byte *table_cache_key(const byte *record,uint *length,
...@@ -2058,8 +2056,8 @@ bool setup_tables(TABLE_LIST *tables) ...@@ -2058,8 +2056,8 @@ bool setup_tables(TABLE_LIST *tables)
} }
static key_map get_key_map_from_key_list(TABLE *table, key_map get_key_map_from_key_list(TABLE *table,
List<String> *index_list) List<String> *index_list)
{ {
key_map map=0; key_map map=0;
List_iterator_fast<String> it(*index_list); List_iterator_fast<String> it(*index_list);
......
...@@ -365,6 +365,7 @@ struct system_variables ...@@ -365,6 +365,7 @@ struct system_variables
ulong net_retry_count; ulong net_retry_count;
ulong net_wait_timeout; ulong net_wait_timeout;
ulong net_write_timeout; ulong net_write_timeout;
ulong preload_buff_size;
ulong query_cache_type; ulong query_cache_type;
ulong read_buff_size; ulong read_buff_size;
ulong read_rnd_buff_size; ulong read_rnd_buff_size;
......
...@@ -59,7 +59,7 @@ enum enum_sql_command { ...@@ -59,7 +59,7 @@ enum enum_sql_command {
SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, SQLCOM_ALTER_DB, SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, SQLCOM_ALTER_DB,
SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT, SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT,
SQLCOM_CREATE_FUNCTION, SQLCOM_DROP_FUNCTION, SQLCOM_CREATE_FUNCTION, SQLCOM_DROP_FUNCTION,
SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK, SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK, SQLCOM_PRELOAD_KEYS,
SQLCOM_FLUSH, SQLCOM_KILL, SQLCOM_ANALYZE, SQLCOM_FLUSH, SQLCOM_KILL, SQLCOM_ANALYZE,
SQLCOM_ROLLBACK, SQLCOM_COMMIT, SQLCOM_SLAVE_START, SQLCOM_SLAVE_STOP, SQLCOM_ROLLBACK, SQLCOM_COMMIT, SQLCOM_SLAVE_START, SQLCOM_SLAVE_STOP,
SQLCOM_BEGIN, SQLCOM_LOAD_MASTER_TABLE, SQLCOM_CHANGE_MASTER, SQLCOM_BEGIN, SQLCOM_LOAD_MASTER_TABLE, SQLCOM_CHANGE_MASTER,
......
...@@ -1819,6 +1819,15 @@ mysql_execute_command(THD *thd) ...@@ -1819,6 +1819,15 @@ mysql_execute_command(THD *thd)
res = mysql_restore_table(thd, tables); res = mysql_restore_table(thd, tables);
break; break;
} }
case SQLCOM_PRELOAD_KEYS:
{
if (check_db_used(thd, tables) ||
check_access(thd, INDEX_ACL, tables->db, &tables->grant.privilege))
goto error;
res = mysql_preload_keys(thd, tables);
break;
}
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
case SQLCOM_CHANGE_MASTER: case SQLCOM_CHANGE_MASTER:
...@@ -3937,6 +3946,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, ...@@ -3937,6 +3946,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
ptr->lock_type= lock_type; ptr->lock_type= lock_type;
ptr->updating= test(table_options & TL_OPTION_UPDATING); ptr->updating= test(table_options & TL_OPTION_UPDATING);
ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX); ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX);
ptr->ignore_leaves= test(table_options & TL_OPTION_IGNORE_LEAVES);
ptr->derived= table->sel; ptr->derived= table->sel;
if (use_index) if (use_index)
ptr->use_index=(List<String> *) thd->memdup((gptr) use_index, ptr->use_index=(List<String> *) thd->memdup((gptr) use_index,
......
...@@ -1331,6 +1331,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, ...@@ -1331,6 +1331,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
goto err; goto err;
continue; continue;
} }
table->table->pos_in_table_list= table;
if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify) if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify)
{ {
char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE]; char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE];
...@@ -1486,6 +1487,28 @@ int mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt) ...@@ -1486,6 +1487,28 @@ int mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
} }
/*
Preload specified indexes for a table into key cache
SYNOPSIS
mysql_preload_keys()
thd Thread object
tables Table list (one table only)
RETURN VALUES
0 ok
-1 error
*/
int mysql_preload_keys(THD* thd, TABLE_LIST* tables)
{
DBUG_ENTER("mysql_preload_keys");
DBUG_RETURN(mysql_admin_table(thd, tables, 0,
"preload_keys", TL_READ, 0, 0, 0,
&handler::preload_keys));
}
/* /*
Create a table identical to the specified table Create a table identical to the specified table
......
...@@ -256,6 +256,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -256,6 +256,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token KEY_SYM %token KEY_SYM
%token LEADING %token LEADING
%token LEAST_SYM %token LEAST_SYM
%token LEAVES
%token LEVEL_SYM %token LEVEL_SYM
%token LEX_HOSTNAME %token LEX_HOSTNAME
%token LIKE %token LIKE
...@@ -309,6 +310,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -309,6 +310,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token DUMPFILE %token DUMPFILE
%token PACK_KEYS_SYM %token PACK_KEYS_SYM
%token PARTIAL %token PARTIAL
%token PRELOAD
%token PRIMARY_SYM %token PRIMARY_SYM
%token PRIVILEGES %token PRIVILEGES
%token PROCESS %token PROCESS
...@@ -584,7 +586,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -584,7 +586,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
type int_type real_type order_dir opt_field_spec lock_option type int_type real_type order_dir opt_field_spec lock_option
udf_type if_exists opt_local opt_table_options table_options udf_type if_exists opt_local opt_table_options table_options
table_option opt_if_not_exists opt_no_write_to_binlog opt_var_type opt_var_ident_type table_option opt_if_not_exists opt_no_write_to_binlog opt_var_type opt_var_ident_type
delete_option opt_temporary all_or_any opt_distinct delete_option opt_temporary all_or_any opt_distinct opt_ignore_leafs
%type <ulong_num> %type <ulong_num>
ULONG_NUM raid_types merge_insert_types ULONG_NUM raid_types merge_insert_types
...@@ -613,7 +615,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -613,7 +615,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
key_alg opt_btree_or_rtree key_alg opt_btree_or_rtree
%type <string_list> %type <string_list>
key_usage_list key_usage_list
%type <key_part> %type <key_part>
key_part key_part
...@@ -661,10 +663,11 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -661,10 +663,11 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%type <NONE> %type <NONE>
query verb_clause create change select do drop insert replace insert2 query verb_clause create change select do drop insert replace insert2
insert_values update delete truncate rename insert_values update delete truncate rename
show describe load alter optimize flush show describe load alter optimize preload flush
reset purge begin commit rollback slave master_def master_defs reset purge begin commit rollback slave master_def master_defs
repair restore backup analyze check start repair restore backup analyze check start
field_list field_list_item field_spec kill column_def key_def field_list field_list_item field_spec kill column_def key_def
preload_list preload_keys
select_item_list select_item values_list no_braces select_item_list select_item values_list no_braces
opt_limit_clause delete_limit_clause fields opt_values values opt_limit_clause delete_limit_clause fields opt_values values
procedure_list procedure_list2 procedure_item procedure_list procedure_list2 procedure_item
...@@ -733,6 +736,7 @@ verb_clause: ...@@ -733,6 +736,7 @@ verb_clause:
| lock | lock
| kill | kill
| optimize | optimize
| preload
| purge | purge
| rename | rename
| repair | repair
...@@ -1824,6 +1828,55 @@ table_to_table: ...@@ -1824,6 +1828,55 @@ table_to_table:
YYABORT; YYABORT;
}; };
preload:
PRELOAD
{
LEX *lex=Lex;
lex->sql_command=SQLCOM_PRELOAD_KEYS;
}
preload_list
{}
;
preload_list:
preload_keys
| preload_list ',' preload_keys;
preload_keys:
table_ident preload_keys_spec opt_ignore_leafs
{
LEX *lex=Lex;
SELECT_LEX *sel= &lex->select_lex;
if (!sel->add_table_to_list(lex->thd, $1, NULL, $3,
TL_READ,
sel->get_use_index(),
(List<String> *)0))
YYABORT;
}
;
preload_keys_spec:
keys_or_index { Select->select_lex()->interval_list.empty(); }
preload_key_list_or_empty
{
LEX *lex=Lex;
SELECT_LEX *sel= &lex->select_lex;
sel->use_index= sel->interval_list;
sel->use_index_ptr= &sel->use_index;
}
;
preload_key_list_or_empty:
/* empty */
| '(' key_usage_list2 ')' {}
;
opt_ignore_leafs:
/* empty */
{ $$= 0; }
| IGNORE_SYM LEAVES { $$= TL_OPTION_IGNORE_LEAVES; }
;
/* /*
Select : retrieve data from table Select : retrieve data from table
*/ */
...@@ -4251,6 +4304,7 @@ keyword: ...@@ -4251,6 +4304,7 @@ keyword:
| INSERT_METHOD {} | INSERT_METHOD {}
| RELAY_THREAD {} | RELAY_THREAD {}
| LAST_SYM {} | LAST_SYM {}
| LEAVES {}
| LEVEL_SYM {} | LEVEL_SYM {}
| LINESTRING {} | LINESTRING {}
| LOCAL_SYM {} | LOCAL_SYM {}
...@@ -4294,6 +4348,7 @@ keyword: ...@@ -4294,6 +4348,7 @@ keyword:
| PASSWORD {} | PASSWORD {}
| POINT_SYM {} | POINT_SYM {}
| POLYGON {} | POLYGON {}
| PRELOAD {}
| PREV_SYM {} | PREV_SYM {}
| PROCESS {} | PROCESS {}
| PROCESSLIST_SYM {} | PROCESSLIST_SYM {}
......
...@@ -181,6 +181,7 @@ typedef struct st_table_list ...@@ -181,6 +181,7 @@ typedef struct st_table_list
bool straight; /* optimize with prev table */ bool straight; /* optimize with prev table */
bool updating; /* for replicate-do/ignore table */ bool updating; /* for replicate-do/ignore table */
bool force_index; /* Prefer index over table scan */ bool force_index; /* Prefer index over table scan */
bool ignore_leaves; /* Preload only non-leaf nodes */
} TABLE_LIST; } TABLE_LIST;
typedef struct st_changed_table_list typedef struct st_changed_table_list
......
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