New result block allocation strategy
This commit is contained in:
parent
558d88f977
commit
11920dbbe7
@ -179,23 +179,23 @@ create table t2 (a text not null);
|
|||||||
create table t21 (a text not null);
|
create table t21 (a text not null);
|
||||||
create table t3 (a text not null);
|
create table t3 (a text not null);
|
||||||
insert into t1 values("1111111111111111111111111111111111111111111111111111");
|
insert into t1 values("1111111111111111111111111111111111111111111111111111");
|
||||||
|
insert into t2 select * from t1;
|
||||||
|
insert into t1 select * from t2;
|
||||||
|
insert into t2 select * from t1;
|
||||||
|
insert into t1 select * from t2;
|
||||||
|
insert into t2 select * from t1;
|
||||||
|
insert into t1 select * from t2;
|
||||||
|
insert into t2 select * from t1;
|
||||||
|
insert into t1 select * from t2;
|
||||||
|
insert into t2 select * from t1;
|
||||||
|
insert into t1 select * from t2;
|
||||||
|
insert into t2 select * from t1;
|
||||||
|
insert into t1 select * from t2;
|
||||||
|
insert into t2 select * from t1;
|
||||||
|
insert into t1 select * from t2;
|
||||||
|
insert into t2 select * from t1;
|
||||||
insert into t11 select * from t1;
|
insert into t11 select * from t1;
|
||||||
insert into t21 select * from t1;
|
insert into t21 select * from t1;
|
||||||
insert into t2 select * from t1;
|
|
||||||
insert into t1 select * from t2;
|
|
||||||
insert into t2 select * from t1;
|
|
||||||
insert into t1 select * from t2;
|
|
||||||
insert into t2 select * from t1;
|
|
||||||
insert into t1 select * from t2;
|
|
||||||
insert into t2 select * from t1;
|
|
||||||
insert into t1 select * from t2;
|
|
||||||
insert into t2 select * from t1;
|
|
||||||
insert into t1 select * from t2;
|
|
||||||
insert into t2 select * from t1;
|
|
||||||
insert into t1 select * from t2;
|
|
||||||
insert into t2 select * from t1;
|
|
||||||
insert into t1 select * from t2;
|
|
||||||
insert into t2 select * from t1;
|
|
||||||
insert into t1 select * from t2;
|
insert into t1 select * from t2;
|
||||||
insert into t2 select * from t1;
|
insert into t2 select * from t1;
|
||||||
insert into t1 select * from t2;
|
insert into t1 select * from t2;
|
||||||
|
@ -93,23 +93,24 @@ create table t2 (a text not null);
|
|||||||
create table t21 (a text not null);
|
create table t21 (a text not null);
|
||||||
create table t3 (a text not null);
|
create table t3 (a text not null);
|
||||||
insert into t1 values("1111111111111111111111111111111111111111111111111111");
|
insert into t1 values("1111111111111111111111111111111111111111111111111111");
|
||||||
|
insert into t2 select * from t1;
|
||||||
|
insert into t1 select * from t2;
|
||||||
|
insert into t2 select * from t1;
|
||||||
|
insert into t1 select * from t2;
|
||||||
|
insert into t2 select * from t1;
|
||||||
|
insert into t1 select * from t2;
|
||||||
|
insert into t2 select * from t1;
|
||||||
|
insert into t1 select * from t2;
|
||||||
|
insert into t2 select * from t1;
|
||||||
|
insert into t1 select * from t2;
|
||||||
|
insert into t2 select * from t1;
|
||||||
|
insert into t1 select * from t2;
|
||||||
|
insert into t2 select * from t1;
|
||||||
|
insert into t1 select * from t2;
|
||||||
|
insert into t2 select * from t1;
|
||||||
|
# t11 and t21 must be over 4Kb (QUERY_CACHE_MIN_RESULT_DATA_SIZE)
|
||||||
insert into t11 select * from t1;
|
insert into t11 select * from t1;
|
||||||
insert into t21 select * from t1;
|
insert into t21 select * from t1;
|
||||||
insert into t2 select * from t1;
|
|
||||||
insert into t1 select * from t2;
|
|
||||||
insert into t2 select * from t1;
|
|
||||||
insert into t1 select * from t2;
|
|
||||||
insert into t2 select * from t1;
|
|
||||||
insert into t1 select * from t2;
|
|
||||||
insert into t2 select * from t1;
|
|
||||||
insert into t1 select * from t2;
|
|
||||||
insert into t2 select * from t1;
|
|
||||||
insert into t1 select * from t2;
|
|
||||||
insert into t2 select * from t1;
|
|
||||||
insert into t1 select * from t2;
|
|
||||||
insert into t2 select * from t1;
|
|
||||||
insert into t1 select * from t2;
|
|
||||||
insert into t2 select * from t1;
|
|
||||||
insert into t1 select * from t2;
|
insert into t1 select * from t2;
|
||||||
insert into t2 select * from t1;
|
insert into t2 select * from t1;
|
||||||
insert into t1 select * from t2;
|
insert into t1 select * from t2;
|
||||||
|
@ -273,9 +273,6 @@ TODO list:
|
|||||||
|
|
||||||
- Invalidate queries that use innoDB tables changed in transaction & remove
|
- Invalidate queries that use innoDB tables changed in transaction & remove
|
||||||
invalidation by table type
|
invalidation by table type
|
||||||
- Allocate bigger blocks for results (may be we should estimate the
|
|
||||||
allocatedblock's size dynamicaly) and shrink last block with
|
|
||||||
results in query_cache_end_of_result.
|
|
||||||
- Delayed till after-parsing qache answer (for column rights processing)
|
- Delayed till after-parsing qache answer (for column rights processing)
|
||||||
- Optimize cache resizing
|
- Optimize cache resizing
|
||||||
- if new_size < old_size then pack & shrink
|
- if new_size < old_size then pack & shrink
|
||||||
@ -657,9 +654,14 @@ void query_cache_end_of_result(NET *net)
|
|||||||
{
|
{
|
||||||
DUMP(&query_cache);
|
DUMP(&query_cache);
|
||||||
BLOCK_LOCK_WR(query_block);
|
BLOCK_LOCK_WR(query_block);
|
||||||
|
Query_cache_query *header = query_block->query();
|
||||||
|
Query_cache_block *last_result_block = header->result()->prev;
|
||||||
|
ulong allign_size = ALIGN_SIZE(last_result_block->used);
|
||||||
|
ulong len = max(query_cache.min_allocation_unit, allign_size);
|
||||||
|
if (last_result_block->length >= query_cache.min_allocation_unit + len)
|
||||||
|
query_cache.split_block(last_result_block,len);
|
||||||
STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
|
STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
|
||||||
|
|
||||||
Query_cache_query *header = query_block->query();
|
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
if (header->result() == 0)
|
if (header->result() == 0)
|
||||||
{
|
{
|
||||||
@ -1585,10 +1587,11 @@ Query_cache::append_result_data(Query_cache_block **current_block,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Try join blocks if physically next block is free...
|
// Try join blocks if physically next block is free...
|
||||||
|
ulong tail = data_len - last_block_free_space;
|
||||||
|
ulong append_min = get_min_append_result_data_size();
|
||||||
if (last_block_free_space < data_len &&
|
if (last_block_free_space < data_len &&
|
||||||
append_next_free_block(last_block,
|
append_next_free_block(last_block,
|
||||||
max(data_len - last_block_free_space,
|
max(tail, append_min)))
|
||||||
QUERY_CACHE_MIN_RESULT_DATA_SIZE)))
|
|
||||||
last_block_free_space = last_block->length - last_block->used;
|
last_block_free_space = last_block->length - last_block->used;
|
||||||
// If no space in last block (even after join) allocate new block
|
// If no space in last block (even after join) allocate new block
|
||||||
if (last_block_free_space < data_len)
|
if (last_block_free_space < data_len)
|
||||||
@ -1648,7 +1651,8 @@ my_bool Query_cache::write_result_data(Query_cache_block **result_block,
|
|||||||
structure_guard_mutex and copy data.
|
structure_guard_mutex and copy data.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
my_bool success = allocate_data_chain(result_block, data_len, query_block);
|
my_bool success = allocate_data_chain(result_block, data_len, query_block,
|
||||||
|
type == Query_cache_block::RES_BEG);
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
// It is success (nobody can prevent us write data)
|
// It is success (nobody can prevent us write data)
|
||||||
@ -1693,13 +1697,28 @@ my_bool Query_cache::write_result_data(Query_cache_block **result_block,
|
|||||||
DBUG_RETURN(success);
|
DBUG_RETURN(success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline ulong Query_cache::get_min_first_result_data_size()
|
||||||
|
{
|
||||||
|
if (queries_in_cache < QUERY_CACHE_MIN_ESTIMATED_QUERIES_NUMBER)
|
||||||
|
return min_result_data_size;
|
||||||
|
ulong avg_result = (query_cache_size - free_memory) / queries_in_cache;
|
||||||
|
avg_result = min(avg_result, query_cache_limit);
|
||||||
|
return max(min_result_data_size, avg_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ulong Query_cache::get_min_append_result_data_size()
|
||||||
|
{
|
||||||
|
return min_result_data_size;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Allocate one or more blocks to hold data
|
Allocate one or more blocks to hold data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
|
my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
|
||||||
ulong data_len,
|
ulong data_len,
|
||||||
Query_cache_block *query_block)
|
Query_cache_block *query_block,
|
||||||
|
my_bool first_block)
|
||||||
{
|
{
|
||||||
ulong all_headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) +
|
ulong all_headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) +
|
||||||
ALIGN_SIZE(sizeof(Query_cache_result)));
|
ALIGN_SIZE(sizeof(Query_cache_result)));
|
||||||
@ -1708,7 +1727,10 @@ my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
|
|||||||
DBUG_PRINT("qcache", ("data_len %lu, all_headers_len %lu",
|
DBUG_PRINT("qcache", ("data_len %lu, all_headers_len %lu",
|
||||||
data_len, all_headers_len));
|
data_len, all_headers_len));
|
||||||
|
|
||||||
*result_block = allocate_block(max(min_result_data_size,len),
|
ulong min_size = (first_block ?
|
||||||
|
get_min_first_result_data_size():
|
||||||
|
get_min_append_result_data_size());
|
||||||
|
*result_block = allocate_block(max(min_size,len),
|
||||||
min_result_data_size == 0,
|
min_result_data_size == 0,
|
||||||
all_headers_len + min_result_data_size,
|
all_headers_len + min_result_data_size,
|
||||||
1);
|
1);
|
||||||
@ -1732,7 +1754,7 @@ my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
|
|||||||
Query_cache_block *next_block;
|
Query_cache_block *next_block;
|
||||||
if ((success = allocate_data_chain(&next_block,
|
if ((success = allocate_data_chain(&next_block,
|
||||||
len - new_block->length,
|
len - new_block->length,
|
||||||
query_block)))
|
query_block, first_block)))
|
||||||
double_linked_list_join(new_block, next_block);
|
double_linked_list_join(new_block, next_block);
|
||||||
}
|
}
|
||||||
if (success)
|
if (success)
|
||||||
@ -1964,7 +1986,7 @@ Query_cache::allocate_block(ulong len, my_bool not_less, ulong min,
|
|||||||
|
|
||||||
if (block != 0) // If we found a suitable block
|
if (block != 0) // If we found a suitable block
|
||||||
{
|
{
|
||||||
if (block->length > ALIGN_SIZE(len) + min_allocation_unit)
|
if (block->length >= ALIGN_SIZE(len) + min_allocation_unit)
|
||||||
split_block(block,ALIGN_SIZE(len));
|
split_block(block,ALIGN_SIZE(len));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2082,7 +2104,11 @@ void Query_cache::split_block(Query_cache_block *block,ulong len)
|
|||||||
new_block->pprev = block;
|
new_block->pprev = block;
|
||||||
new_block->pnext->pprev = new_block;
|
new_block->pnext->pprev = new_block;
|
||||||
|
|
||||||
|
if (block->type == Query_cache_block::FREE)
|
||||||
|
// if block was free then it already joined with all free neighbours
|
||||||
insert_into_free_memory_list(new_block);
|
insert_into_free_memory_list(new_block);
|
||||||
|
else
|
||||||
|
free_memory_block(new_block);
|
||||||
|
|
||||||
DBUG_PRINT("qcache", ("split 0x%lx (%lu) new 0x%lx",
|
DBUG_PRINT("qcache", ("split 0x%lx (%lu) new 0x%lx",
|
||||||
(ulong) block, len, (ulong) new_block));
|
(ulong) block, len, (ulong) new_block));
|
||||||
|
@ -25,14 +25,22 @@
|
|||||||
if QUERY_CACHE_MIN_ALLOCATION_UNIT == 0 then
|
if QUERY_CACHE_MIN_ALLOCATION_UNIT == 0 then
|
||||||
QUERY_CACHE_MIN_ALLOCATION_UNIT choosed automaticaly
|
QUERY_CACHE_MIN_ALLOCATION_UNIT choosed automaticaly
|
||||||
*/
|
*/
|
||||||
#define QUERY_CACHE_MIN_ALLOCATION_UNIT 0
|
#define QUERY_CACHE_MIN_ALLOCATION_UNIT 512
|
||||||
|
|
||||||
/* inittial size of hashes */
|
/* inittial size of hashes */
|
||||||
#define QUERY_CACHE_DEF_QUERY_HASH_SIZE 1024
|
#define QUERY_CACHE_DEF_QUERY_HASH_SIZE 1024
|
||||||
#define QUERY_CACHE_DEF_TABLE_HASH_SIZE 1024
|
#define QUERY_CACHE_DEF_TABLE_HASH_SIZE 1024
|
||||||
|
|
||||||
/* minimal result data size when data allocated */
|
/* minimal result data size when data allocated */
|
||||||
#define QUERY_CACHE_MIN_RESULT_DATA_SIZE 1024
|
#define QUERY_CACHE_MIN_RESULT_DATA_SIZE 1024*4
|
||||||
|
|
||||||
|
/*
|
||||||
|
start estimation of first result block size only when number of queries
|
||||||
|
bigger then:
|
||||||
|
*/
|
||||||
|
#define QUERY_CACHE_MIN_ESTIMATED_QUERIES_NUMBER 3
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* memory bins size spacing (see at Query_cache::init_cache (sql_cache.cc)) */
|
/* memory bins size spacing (see at Query_cache::init_cache (sql_cache.cc)) */
|
||||||
#define QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2 4
|
#define QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2 4
|
||||||
@ -234,8 +242,7 @@ protected:
|
|||||||
query structure we locked an internal query block mutex.
|
query structure we locked an internal query block mutex.
|
||||||
LOCK SEQUENCE (to prevent deadlocks):
|
LOCK SEQUENCE (to prevent deadlocks):
|
||||||
1. structure_guard_mutex
|
1. structure_guard_mutex
|
||||||
2. query block / table block / free block
|
2. query block (for operation inside query (query block/results))
|
||||||
3. results blocks (only when must become free).
|
|
||||||
*/
|
*/
|
||||||
pthread_mutex_t structure_guard_mutex;
|
pthread_mutex_t structure_guard_mutex;
|
||||||
byte *cache; // cache memory
|
byte *cache; // cache memory
|
||||||
@ -271,7 +278,8 @@ protected:
|
|||||||
void free_query(Query_cache_block *point);
|
void free_query(Query_cache_block *point);
|
||||||
my_bool allocate_data_chain(Query_cache_block **result_block,
|
my_bool allocate_data_chain(Query_cache_block **result_block,
|
||||||
ulong data_len,
|
ulong data_len,
|
||||||
Query_cache_block *query_block);
|
Query_cache_block *query_block,
|
||||||
|
my_bool first_block);
|
||||||
void invalidate_table(TABLE_LIST *table);
|
void invalidate_table(TABLE_LIST *table);
|
||||||
void invalidate_table(TABLE *table);
|
void invalidate_table(TABLE *table);
|
||||||
void invalidate_table(Query_cache_block *table_block);
|
void invalidate_table(Query_cache_block *table_block);
|
||||||
@ -328,6 +336,8 @@ protected:
|
|||||||
Query_cache_block *parent,
|
Query_cache_block *parent,
|
||||||
Query_cache_block::block_type
|
Query_cache_block::block_type
|
||||||
type=Query_cache_block::RESULT);
|
type=Query_cache_block::RESULT);
|
||||||
|
inline ulong get_min_first_result_data_size();
|
||||||
|
inline ulong get_min_append_result_data_size();
|
||||||
Query_cache_block *allocate_block(ulong len, my_bool not_less,
|
Query_cache_block *allocate_block(ulong len, my_bool not_less,
|
||||||
ulong min,
|
ulong min,
|
||||||
my_bool under_guard=0);
|
my_bool under_guard=0);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user