66
67
/*--------------------------------------*/
67
68
#define BTR_BLOB_HDR_SIZE 8
70
/* Estimated table level stats from sampled value. */
71
#define BTR_TABLE_STATS_FROM_SAMPLE(value, index, ext_size, not_empty) \
72
((value * (ib_longlong) index->stat_n_leaf_pages \
73
+ BTR_KEY_VAL_ESTIMATE_N_PAGES - 1 + ext_size \
75
/ (BTR_KEY_VAL_ESTIMATE_N_PAGES + ext_size))
77
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
78
/* A BLOB field reference full of zero, for use in assertions and tests.
79
Initially, BLOB field references are set to zero, in
80
dtuple_convert_big_rec(). */
81
const byte field_ref_zero[BTR_EXTERN_FIELD_REF_SIZE];
82
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
69
84
/***********************************************************************
70
85
Marks all extern fields in a record as owned by the record. This function
71
86
should be called if the delete mark of a record is removed: a not delete
1579
1593
heap = mem_heap_create(1024);
1580
1594
offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap);
1595
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
1596
ut_a(!rec_offs_any_null_extern(rec, offsets)
1597
|| thr_get_trx(thr) == trx_roll_crash_recv_trx);
1598
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
1582
1600
#ifdef UNIV_DEBUG
1583
1601
if (btr_cur_print_record_ops && thr) {
1685
1703
page_cur_move_to_prev(page_cursor);
1687
trx = thr_get_trx(thr);
1689
1705
if (!(flags & BTR_KEEP_SYS_FLAG)) {
1690
1706
row_upd_index_entry_sys_field(new_entry, index, DATA_ROLL_PTR,
1692
1708
row_upd_index_entry_sys_field(new_entry, index, DATA_TRX_ID,
1709
thr_get_trx(thr)->id);
1696
1712
rec = btr_cur_insert_if_possible(cursor, new_entry, &reorganized, mtr);
2837
2853
/***********************************************************************
2854
Record the number of non_null key values in a given index for
2855
each n-column prefix of the index where n < dict_index_get_n_unique(index).
2856
The estimates are eventually stored in the array:
2857
index->stat_n_non_null_key_vals. */
2860
btr_record_not_null_field_in_rec(
2861
/*=============================*/
2862
ulint n_unique, /* in: dict_index_get_n_unique(index),
2863
number of columns uniquely determine
2865
const ulint* offsets, /* in: rec_get_offsets(rec, index),
2866
its size could be for all fields or
2867
that of "n_unique" */
2868
ib_longlong* n_not_null) /* in/out: array to record number of
2869
not null rows for n-column prefix */
2873
ut_ad(rec_offs_n_fields(offsets) >= n_unique);
2875
if (n_not_null == NULL) {
2879
for (i = 0; i < n_unique; i++) {
2880
if (rec_offs_nth_sql_null(offsets, i)) {
2888
/***********************************************************************
2838
2889
Estimates the number of different key values in a given index, for
2839
2890
each n-column prefix of the index where n <= dict_index_get_n_unique(index).
2840
The estimates are stored in the array index->stat_n_diff_key_vals. */
2891
The estimates are stored in the array index->stat_n_diff_key_vals.
2892
If innodb_stats_method is "nulls_ignored", we also record the number of
2893
non-null values for each prefix and store the estimates in
2894
array index->stat_n_non_null_key_vals. */
2843
2897
btr_estimate_number_of_different_key_vals(
2860
2916
mem_heap_t* heap = NULL;
2861
ulint offsets_rec_[REC_OFFS_NORMAL_SIZE];
2862
ulint offsets_next_rec_[REC_OFFS_NORMAL_SIZE];
2863
ulint* offsets_rec = offsets_rec_;
2864
ulint* offsets_next_rec= offsets_next_rec_;
2865
*offsets_rec_ = (sizeof offsets_rec_) / sizeof *offsets_rec_;
2867
= (sizeof offsets_next_rec_) / sizeof *offsets_next_rec_;
2917
ulint* offsets_rec = NULL;
2918
ulint* offsets_next_rec = NULL;
2869
2920
n_cols = dict_index_get_n_unique(index);
2871
n_diff = mem_alloc((n_cols + 1) * sizeof(ib_longlong));
2873
memset(n_diff, 0, (n_cols + 1) * sizeof(ib_longlong));
2922
heap = mem_heap_create((sizeof *n_diff + sizeof *n_not_null)
2924
+ dict_index_get_n_fields(index)
2925
* (sizeof *offsets_rec
2926
+ sizeof *offsets_next_rec));
2928
n_diff = mem_heap_zalloc(heap, (n_cols + 1) * sizeof(ib_longlong));
2932
/* Check srv_innodb_stats_method setting, and decide whether we
2933
need to record non-null value and also decide if NULL is
2934
considered equal (by setting stats_null_not_equal value) */
2935
switch (srv_innodb_stats_method) {
2936
case SRV_STATS_NULLS_IGNORED:
2937
n_not_null = mem_heap_zalloc(heap, (n_cols + 1)
2938
* sizeof *n_not_null);
2941
case SRV_STATS_NULLS_UNEQUAL:
2942
/* for both SRV_STATS_NULLS_IGNORED and SRV_STATS_NULLS_UNEQUAL
2943
case, we will treat NULLs as unequal value */
2944
stats_null_not_equal = TRUE;
2947
case SRV_STATS_NULLS_EQUAL:
2948
stats_null_not_equal = FALSE;
2875
2955
/* We sample some pages in the index to get an estimate */
2877
2957
for (i = 0; i < BTR_KEY_VAL_ESTIMATE_N_PAGES; i++) {
2879
2958
mtr_start(&mtr);
2881
2960
btr_cur_open_at_rnd_pos(index, BTR_SEARCH_LEAF, &cursor, &mtr);
2889
2968
page = btr_cur_get_page(&cursor);
2891
supremum = page_get_supremum_rec(page);
2892
2970
rec = page_rec_get_next(page_get_infimum_rec(page));
2894
if (rec != supremum) {
2972
if (!page_rec_is_supremum(rec)) {
2895
2973
not_empty_flag = 1;
2896
2974
offsets_rec = rec_get_offsets(rec, index, offsets_rec,
2897
2975
ULINT_UNDEFINED, &heap);
2978
btr_record_not_null_field_in_rec(
2979
n_cols, offsets_rec, n_not_null);
2900
while (rec != supremum) {
2983
while (!page_rec_is_supremum(rec)) {
2901
2984
rec_t* next_rec = page_rec_get_next(rec);
2902
if (next_rec == supremum) {
2985
if (page_rec_is_supremum(next_rec)) {
2986
total_external_size +=
2987
btr_rec_get_externally_stored_len(
2907
2993
matched_bytes = 0;
2908
2994
offsets_next_rec = rec_get_offsets(next_rec, index,
2909
2995
offsets_next_rec,
2912
2999
cmp_rec_rec_with_match(rec, next_rec,
2913
3000
offsets_rec, offsets_next_rec,
2914
index, &matched_fields,
3001
index, stats_null_not_equal,
2915
3003
&matched_bytes);
2917
3005
for (j = matched_fields + 1; j <= n_cols; j++) {
2971
3060
included in index->stat_n_leaf_pages) */
2973
3062
for (j = 0; j <= n_cols; j++) {
2974
index->stat_n_diff_key_vals[j]
2976
* (ib_longlong)index->stat_n_leaf_pages
2977
+ BTR_KEY_VAL_ESTIMATE_N_PAGES - 1
2978
+ total_external_size
2980
/ (BTR_KEY_VAL_ESTIMATE_N_PAGES
2981
+ total_external_size));
3063
index->stat_n_diff_key_vals[j] = BTR_TABLE_STATS_FROM_SAMPLE(
3064
n_diff[j], index, total_external_size, not_empty_flag);
2983
3066
/* If the tree is small, smaller than
2984
3067
10 * BTR_KEY_VAL_ESTIMATE_N_PAGES + total_external_size, then
2999
3082
index->stat_n_diff_key_vals[j] += add_on;
3003
if (UNIV_LIKELY_NULL(heap)) {
3004
mem_heap_free(heap);
3084
/* Update the stat_n_non_null_key_vals[] with our
3085
sampled result. stat_n_non_null_key_vals[] is created
3086
and initialized to zero in dict_index_add_to_cache(),
3087
along with stat_n_diff_key_vals[] array */
3088
if (n_not_null != NULL && (j < n_cols)) {
3089
index->stat_n_non_null_key_vals[j] =
3090
BTR_TABLE_STATS_FROM_SAMPLE(
3091
n_not_null[j], index,
3092
total_external_size, not_empty_flag);
3096
mem_heap_free(heap);
3008
3099
/*================== EXTERNAL STORAGE OF BIG FIELDS ===================*/