Commit 4fb0e5e7 authored by marko's avatar marko

branches/zip: Account for the compressed page size when checking if a

record will fit or need external storage.

btr_page_get_sure_split_rec(): Estimate the free space of an empty
compressed page.

page_zip_rec_needs_ext(): New function, to replace existing tests whether
external storage is needed.
parent 41468be9
...@@ -1301,6 +1301,7 @@ btr_page_get_sure_split_rec( ...@@ -1301,6 +1301,7 @@ btr_page_get_sure_split_rec(
dtuple_t* tuple) /* in: tuple to insert */ dtuple_t* tuple) /* in: tuple to insert */
{ {
page_t* page; page_t* page;
page_zip_des_t* page_zip;
ulint insert_size; ulint insert_size;
ulint free_space; ulint free_space;
ulint total_data; ulint total_data;
...@@ -1319,6 +1320,20 @@ btr_page_get_sure_split_rec( ...@@ -1319,6 +1320,20 @@ btr_page_get_sure_split_rec(
insert_size = rec_get_converted_size(cursor->index, tuple); insert_size = rec_get_converted_size(cursor->index, tuple);
free_space = page_get_free_space_of_empty(page_is_comp(page)); free_space = page_get_free_space_of_empty(page_is_comp(page));
page_zip = buf_block_get_page_zip(buf_block_align(page));
if (UNIV_LIKELY_NULL(page_zip)) {
/* Estimate the free space of an empty compressed page.
The space needed for compressing the index information
is estimated. */
ulint free_space_zip = page_zip->size
- PAGE_DATA - cursor->index->n_fields / 2;
if (UNIV_LIKELY(free_space > free_space_zip)) {
free_space = free_space_zip;
ut_a(insert_size <= free_space);
}
}
/* free_space is now the free space of a created new page */ /* free_space is now the free space of a created new page */
total_data = page_get_data_size(page) + insert_size; total_data = page_get_data_size(page) + insert_size;
......
...@@ -1026,6 +1026,7 @@ btr_cur_optimistic_insert( ...@@ -1026,6 +1026,7 @@ btr_cur_optimistic_insert(
page = btr_cur_get_page(cursor); page = btr_cur_get_page(cursor);
index = cursor->index; index = cursor->index;
page_zip = buf_block_get_page_zip(buf_block_align(page));
if (!dtuple_check_typed_no_assert(entry)) { if (!dtuple_check_typed_no_assert(entry)) {
fputs("InnoDB: Error in a tuple to insert into ", stderr); fputs("InnoDB: Error in a tuple to insert into ", stderr);
...@@ -1047,9 +1048,8 @@ calculate_sizes_again: ...@@ -1047,9 +1048,8 @@ calculate_sizes_again:
/* Calculate the record size when entry is converted to a record */ /* Calculate the record size when entry is converted to a record */
rec_size = rec_get_converted_size(index, entry); rec_size = rec_get_converted_size(index, entry);
if (rec_size >= if (page_zip_rec_needs_ext(rec_size, page_is_comp(page),
ut_min(page_get_free_space_of_empty(page_is_comp(page)) / 2, page_zip ? page_zip->size : 0)) {
REC_MAX_DATA_SIZE)) {
/* The record is so big that we have to store some fields /* The record is so big that we have to store some fields
externally on separate database pages */ externally on separate database pages */
...@@ -1130,7 +1130,6 @@ calculate_sizes_again: ...@@ -1130,7 +1130,6 @@ calculate_sizes_again:
} }
/* Now, try the insert */ /* Now, try the insert */
page_zip = buf_block_get_page_zip(buf_block_align(page));
*rec = page_cur_tuple_insert(page_cursor, page_zip, *rec = page_cur_tuple_insert(page_cursor, page_zip,
entry, index, ext, n_ext, mtr); entry, index, ext, n_ext, mtr);
...@@ -1289,10 +1288,9 @@ btr_cur_pessimistic_insert( ...@@ -1289,10 +1288,9 @@ btr_cur_pessimistic_insert(
} }
} }
if (rec_get_converted_size(index, entry) >= if (page_zip_rec_needs_ext(rec_get_converted_size(index, entry),
ut_min(page_get_free_space_of_empty(page_is_comp(page)) / 2, page_is_comp(page),
REC_MAX_DATA_SIZE)) { dict_table_zip_size(index->table))) {
/* The record is so big that we have to store some fields /* The record is so big that we have to store some fields
externally on separate database pages */ externally on separate database pages */
...@@ -2059,9 +2057,8 @@ btr_cur_pessimistic_update( ...@@ -2059,9 +2057,8 @@ btr_cur_pessimistic_update(
ULINT_UNDEFINED, &heap); ULINT_UNDEFINED, &heap);
n_ext_vect = btr_push_update_extern_fields(ext_vect, offsets, update); n_ext_vect = btr_push_update_extern_fields(ext_vect, offsets, update);
if (UNIV_UNLIKELY(rec_get_converted_size(index, new_entry) >= if (page_zip_rec_needs_ext(rec_get_converted_size(index, new_entry),
ut_min(page_get_free_space_of_empty(page_is_comp(page)) / 2, page_is_comp(page), page_zip ? page_zip->size : 0)) {
REC_MAX_DATA_SIZE))) {
ulint i; ulint i;
big_rec_vec = dtuple_convert_big_rec(index, new_entry, big_rec_vec = dtuple_convert_big_rec(index, new_entry,
......
...@@ -532,10 +532,9 @@ dtuple_convert_big_rec( ...@@ -532,10 +532,9 @@ dtuple_convert_big_rec(
n_fields = 0; n_fields = 0;
while (rec_get_converted_size(index, entry) while (page_zip_rec_needs_ext(rec_get_converted_size(index, entry),
>= ut_min(page_get_free_space_of_empty( dict_table_is_comp(index->table),
dict_table_is_comp(index->table)) / 2, dict_table_zip_size(index->table))) {
REC_MAX_DATA_SIZE)) {
longest = 0; longest = 0;
for (i = dict_index_get_n_unique_in_tree(index); for (i = dict_index_get_n_unique_in_tree(index);
......
...@@ -19,6 +19,19 @@ Created June 2005 by Marko Makela ...@@ -19,6 +19,19 @@ Created June 2005 by Marko Makela
#include "dict0types.h" #include "dict0types.h"
#include "ut0byte.h" #include "ut0byte.h"
/**************************************************************************
Determine if a record is so big that it needs to be stored externally. */
UNIV_INLINE
ibool
page_zip_rec_needs_ext(
/*===================*/
/* out: FALSE if the entire record
can be stored locally on the page */
ulint rec_size, /* in: length of the record in bytes */
ulint comp, /* in: nonzero=compact format */
ulint zip_size) /* in: compressed page size in bytes, or 0 */
__attribute__((const));
/************************************************************************** /**************************************************************************
Initialize a compressed page descriptor. */ Initialize a compressed page descriptor. */
UNIV_INLINE UNIV_INLINE
......
...@@ -92,6 +92,44 @@ In summary, the compressed page looks like this: ...@@ -92,6 +92,44 @@ In summary, the compressed page looks like this:
/* 'deleted' flag */ /* 'deleted' flag */
#define PAGE_ZIP_DIR_SLOT_DEL 0x8000 #define PAGE_ZIP_DIR_SLOT_DEL 0x8000
/**************************************************************************
Determine if a record is so big that it needs to be stored externally. */
UNIV_INLINE
ibool
page_zip_rec_needs_ext(
/*===================*/
/* out: FALSE if the entire record
can be stored locally on the page */
ulint rec_size, /* in: length of the record in bytes */
ulint comp, /* in: nonzero=compact format */
ulint zip_size) /* in: compressed page size in bytes, or 0 */
{
ut_ad(rec_size > comp ? REC_N_NEW_EXTRA_BYTES : REC_N_OLD_EXTRA_BYTES);
ut_ad(ut_is_2pow(zip_size));
#if UNIV_PAGE_SIZE > REC_MAX_DATA_SIZE
if (UNIV_UNLIKELY(rec_size >= REC_MAX_DATA_SIZE)) {
return(TRUE);
}
#endif
if (UNIV_UNLIKELY(!comp)) {
ut_ad(!zip_size);
return(rec_size >= page_get_free_space_of_empty(FALSE) / 2);
}
/* If zip_size != 0, the record should fit on the compressed page.
If not, the right-hand-side of the comparison will overwrap
and the condition will not hold. Thus, we do not need to test
for zip_size != 0. We subtract the size of the page header and
assume that compressing the index information takes 50 bytes. */
if (rec_size >= zip_size - (PAGE_DATA + 50)) {
return(TRUE);
}
return(rec_size >= page_get_free_space_of_empty(TRUE) / 2);
}
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
/************************************************************************** /**************************************************************************
Validate a compressed page descriptor. */ Validate a compressed page descriptor. */
......
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