~tsarev/percona-server/bug721176_2

2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1
# name       : innodb_stats.patch
2
# introduced : 11 or before
3
# maintainer : Yasufumi
4
#
5
#!!! notice !!!
6
# Any small change to this file in the main branch
7
# should be done or reviewed by the maintainer!
148.1.3 by Oleg Tsarev
port patches to 5.5.15
8
--- a/storage/innobase/dict/dict0boot.c
9
+++ b/storage/innobase/dict/dict0boot.c
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
10
@@ -266,6 +266,29 @@
11
 	/* Get the dictionary header */
12
 	dict_hdr = dict_hdr_get(&mtr);
13
 
14
+	if (mach_read_from_8(dict_hdr + DICT_HDR_XTRADB_MARK)
15
+	    != DICT_HDR_XTRADB_FLAG) {
16
+		/* not extended yet by XtraDB, need to be extended */
17
+		ulint	root_page_no;
18
+
19
+		root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
20
+					  DICT_HDR_SPACE, 0, DICT_STATS_ID,
21
+					  dict_ind_redundant, &mtr);
22
+		if (root_page_no == FIL_NULL) {
23
+			fprintf(stderr, "InnoDB: Warning: failed to create SYS_STATS btr.\n");
24
+			srv_use_sys_stats_table = FALSE;
25
+		} else {
26
+			mlog_write_ulint(dict_hdr + DICT_HDR_STATS, root_page_no,
27
+					 MLOG_4BYTES, &mtr);
28
+			mlog_write_ull(dict_hdr + DICT_HDR_XTRADB_MARK,
29
+					  DICT_HDR_XTRADB_FLAG, &mtr);
30
+		}
31
+		mtr_commit(&mtr);
32
+		/* restart mtr */
33
+		mtr_start(&mtr);
34
+		dict_hdr = dict_hdr_get(&mtr);
35
+	}
36
+
37
 	/* Because we only write new row ids to disk-based data structure
38
 	(dictionary header) when it is divisible by
39
 	DICT_HDR_ROW_ID_WRITE_MARGIN, in recovery we will not recover
40
@@ -425,7 +448,7 @@
41
 	table->id = DICT_FIELDS_ID;
42
 	dict_table_add_to_cache(table, heap);
43
 	dict_sys->sys_fields = table;
44
-	mem_heap_free(heap);
45
+	mem_heap_empty(heap);
46
 
47
 	index = dict_mem_index_create("SYS_FIELDS", "CLUST_IND",
48
 				      DICT_HDR_SPACE,
92.1.1 by Yasufumi Kinoshita
fix bug733317
49
@@ -442,6 +465,45 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
50
 					FALSE);
51
 	ut_a(error == DB_SUCCESS);
52
 
53
+	/*-------------------------*/
92.1.1 by Yasufumi Kinoshita
fix bug733317
54
+	table = dict_mem_table_create("SYS_STATS", DICT_HDR_SPACE, 4, 0);
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
55
+	table->n_mysql_handles_opened = 1; /* for pin */
56
+
57
+	dict_mem_table_add_col(table, heap, "INDEX_ID", DATA_BINARY, 0, 0);
58
+	dict_mem_table_add_col(table, heap, "KEY_COLS", DATA_INT, 0, 4);
59
+	dict_mem_table_add_col(table, heap, "DIFF_VALS", DATA_BINARY, 0, 0);
92.1.1 by Yasufumi Kinoshita
fix bug733317
60
+	dict_mem_table_add_col(table, heap, "NON_NULL_VALS", DATA_BINARY, 0, 0);
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
61
+
62
+	/* The '+ 2' below comes from the fields DB_TRX_ID, DB_ROLL_PTR */
63
+#if DICT_SYS_STATS_DIFF_VALS_FIELD != 2 + 2
64
+#error "DICT_SYS_STATS_DIFF_VALS_FIELD != 2 + 2"
65
+#endif
92.1.1 by Yasufumi Kinoshita
fix bug733317
66
+#if DICT_SYS_STATS_NON_NULL_VALS_FIELD != 3 + 2
67
+#error "DICT_SYS_STATS_NON_NULL_VALS_FIELD != 3 + 2"
68
+#endif
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
69
+
70
+	table->id = DICT_STATS_ID;
71
+	dict_table_add_to_cache(table, heap);
72
+	dict_sys->sys_stats = table;
73
+	mem_heap_empty(heap);
74
+
75
+	index = dict_mem_index_create("SYS_STATS", "CLUST_IND",
76
+				      DICT_HDR_SPACE,
77
+				      DICT_UNIQUE | DICT_CLUSTERED, 2);
78
+
79
+	dict_mem_index_add_field(index, "INDEX_ID", 0);
80
+	dict_mem_index_add_field(index, "KEY_COLS", 0);
81
+
82
+	index->id = DICT_STATS_ID;
83
+	error = dict_index_add_to_cache(table, index,
84
+					mtr_read_ulint(dict_hdr
85
+						       + DICT_HDR_STATS,
86
+						       MLOG_4BYTES, &mtr),
87
+					FALSE);
88
+	ut_a(error == DB_SUCCESS);
89
+
90
+	mem_heap_free(heap);
91
+
92
 	mtr_commit(&mtr);
93
 	/*-------------------------*/
94
 
92.1.1 by Yasufumi Kinoshita
fix bug733317
95
@@ -455,6 +517,7 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
96
 	dict_load_sys_table(dict_sys->sys_columns);
97
 	dict_load_sys_table(dict_sys->sys_indexes);
98
 	dict_load_sys_table(dict_sys->sys_fields);
99
+	dict_load_sys_table(dict_sys->sys_stats);
100
 
101
 	mutex_exit(&(dict_sys->mutex));
102
 }
148.1.3 by Oleg Tsarev
port patches to 5.5.15
103
--- a/storage/innobase/dict/dict0crea.c
104
+++ b/storage/innobase/dict/dict0crea.c
92.1.1 by Yasufumi Kinoshita
fix bug733317
105
@@ -508,6 +508,56 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
106
 }
107
 
108
 /*****************************************************************//**
109
+Based on an index object, this function builds the entry to be inserted
110
+in the SYS_STATS system table.
111
+@return	the tuple which should be inserted */
112
+static
113
+dtuple_t*
114
+dict_create_sys_stats_tuple(
115
+/*========================*/
116
+	const dict_index_t*	index,
117
+	ulint			i,
118
+	mem_heap_t*		heap)
119
+{
120
+	dict_table_t*	sys_stats;
121
+	dtuple_t*	entry;
122
+	dfield_t*	dfield;
123
+	byte*		ptr;
124
+
125
+	ut_ad(index);
126
+	ut_ad(heap);
127
+
128
+	sys_stats = dict_sys->sys_stats;
129
+
92.1.1 by Yasufumi Kinoshita
fix bug733317
130
+	entry = dtuple_create(heap, 4 + DATA_N_SYS_COLS);
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
131
+
132
+	dict_table_copy_types(entry, sys_stats);
133
+
134
+	/* 0: INDEX_ID -----------------------*/
135
+	dfield = dtuple_get_nth_field(entry, 0/*INDEX_ID*/);
136
+	ptr = mem_heap_alloc(heap, 8);
137
+	mach_write_to_8(ptr, index->id);
138
+	dfield_set_data(dfield, ptr, 8);
139
+	/* 1: KEY_COLS -----------------------*/
140
+	dfield = dtuple_get_nth_field(entry, 1/*KEY_COLS*/);
141
+	ptr = mem_heap_alloc(heap, 4);
142
+	mach_write_to_4(ptr, i);
143
+	dfield_set_data(dfield, ptr, 4);
144
+	/* 4: DIFF_VALS ----------------------*/
145
+	dfield = dtuple_get_nth_field(entry, 2/*DIFF_VALS*/);
146
+	ptr = mem_heap_alloc(heap, 8);
147
+	mach_write_to_8(ptr, 0); /* initial value is 0 */
148
+	dfield_set_data(dfield, ptr, 8);
92.1.1 by Yasufumi Kinoshita
fix bug733317
149
+	/* 5: NON_NULL_VALS ------------------*/
150
+	dfield = dtuple_get_nth_field(entry, 3/*NON_NULL_VALS*/);
151
+	ptr = mem_heap_alloc(heap, 8);
152
+	mach_write_to_8(ptr, 0); /* initial value is 0 */
153
+	dfield_set_data(dfield, ptr, 8);
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
154
+
155
+	return(entry);
156
+}
157
+
158
+/*****************************************************************//**
159
 Creates the tuple with which the index entry is searched for writing the index
160
 tree root page number, if such a tree is created.
161
 @return	the tuple for search */
92.1.1 by Yasufumi Kinoshita
fix bug733317
162
@@ -617,6 +667,27 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
163
 }
164
 
165
 /***************************************************************//**
166
+Builds a row for storing stats to insert.
167
+@return DB_SUCCESS */
168
+static
169
+ulint
170
+dict_build_stats_def_step(
171
+/*======================*/
172
+	ind_node_t*	node)
173
+{
174
+	dict_index_t*	index;
175
+	dtuple_t*	row;
176
+
177
+	index = node->index;
178
+
179
+	row = dict_create_sys_stats_tuple(index, node->stats_no, node->heap);
180
+
181
+	ins_node_set_new_row(node->stats_def, row);
182
+
183
+	return(DB_SUCCESS);
184
+}
185
+
186
+/***************************************************************//**
187
 Creates an index tree for the index if it is not a member of a cluster.
188
 @return	DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
189
 static
136.3.2 by Yasufumi Kinoshita
Yasufumi patches are ported to 5.5.14
190
@@ -936,6 +1007,49 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
191
 					  dict_sys->sys_fields, heap);
192
 	node->field_def->common.parent = node;
193
 
194
+	if (srv_use_sys_stats_table) {
195
+		node->stats_def = ins_node_create(INS_DIRECT,
196
+						  dict_sys->sys_stats, heap);
197
+		node->stats_def->common.parent = node;
198
+	} else {
199
+		node->stats_def = NULL;
200
+	}
201
+
202
+	node->commit_node = commit_node_create(heap);
203
+	node->commit_node->common.parent = node;
204
+
205
+	return(node);
206
+}
207
+
208
+/*********************************************************************//**
209
+*/
210
+UNIV_INTERN
211
+ind_node_t*
212
+ind_insert_stats_graph_create(
213
+/*==========================*/
214
+	dict_index_t*	index,
215
+	mem_heap_t*	heap)
216
+{
217
+	ind_node_t*	node;
218
+
219
+	node = mem_heap_alloc(heap, sizeof(ind_node_t));
220
+
221
+	node->common.type = QUE_NODE_INSERT_STATS;
222
+
223
+	node->index = index;
224
+
225
+	node->state = INDEX_BUILD_STATS_COLS;
226
+	node->page_no = FIL_NULL;
227
+	node->heap = mem_heap_create(256);
228
+
229
+	node->ind_def = NULL;
230
+	node->field_def = NULL;
231
+
232
+	node->stats_def = ins_node_create(INS_DIRECT,
233
+					  dict_sys->sys_stats, heap);
234
+	node->stats_def->common.parent = node;
235
+	node->stats_no = 0;
236
+
237
 	node->commit_node = commit_node_create(heap);
238
 	node->commit_node->common.parent = node;
239
 
136.3.2 by Yasufumi Kinoshita
Yasufumi patches are ported to 5.5.14
240
@@ -1086,6 +1200,7 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
241
 
242
 		node->state = INDEX_BUILD_FIELD_DEF;
243
 		node->field_no = 0;
244
+		node->stats_no = 0;
245
 
246
 		thr->run_node = node->ind_def;
247
 
136.3.2 by Yasufumi Kinoshita
Yasufumi patches are ported to 5.5.14
248
@@ -1131,7 +1246,31 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
249
 			goto function_exit;
250
 		}
251
 
252
-		node->state = INDEX_CREATE_INDEX_TREE;
253
+		if (srv_use_sys_stats_table
254
+		    && !((node->table->flags >> DICT_TF2_SHIFT) & DICT_TF2_TEMPORARY)) {
255
+			node->state = INDEX_BUILD_STATS_COLS;
256
+		} else {
257
+			node->state = INDEX_CREATE_INDEX_TREE;
258
+		}
259
+	}
260
+	if (node->state == INDEX_BUILD_STATS_COLS) {
261
+		if (node->stats_no <= dict_index_get_n_unique(node->index)) {
262
+
263
+			err = dict_build_stats_def_step(node);
264
+
265
+			if (err != DB_SUCCESS) {
266
+
267
+				goto function_exit;
268
+			}
269
+
270
+			node->stats_no++;
271
+
272
+			thr->run_node = node->stats_def;
273
+
274
+			return(thr);
275
+		} else {
276
+			node->state = INDEX_CREATE_INDEX_TREE;
277
+		}
278
 	}
279
 
280
 	if (node->state == INDEX_CREATE_INDEX_TREE) {
148.1.3 by Oleg Tsarev
port patches to 5.5.15
281
@@ -1183,6 +1322,66 @@
282
 }
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
283
 
148.1.3 by Oleg Tsarev
port patches to 5.5.15
284
 /****************************************************************//**
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
285
+*/
286
+UNIV_INTERN
287
+que_thr_t*
288
+dict_insert_stats_step(
289
+/*===================*/
290
+	que_thr_t*	thr)	/*!< in: query thread */
291
+{
292
+	ind_node_t*	node;
293
+	ulint		err	= DB_ERROR;
294
+	trx_t*		trx;
295
+
296
+	ut_ad(thr);
297
+
298
+	trx = thr_get_trx(thr);
299
+
300
+	node = thr->run_node;
301
+
302
+	if (thr->prev_node == que_node_get_parent(node)) {
303
+		node->state = INDEX_BUILD_STATS_COLS;
304
+	}
305
+
306
+	if (node->state == INDEX_BUILD_STATS_COLS) {
307
+		if (node->stats_no <= dict_index_get_n_unique(node->index)) {
308
+
309
+			err = dict_build_stats_def_step(node);
310
+
311
+			if (err != DB_SUCCESS) {
312
+
313
+				goto function_exit;
314
+			}
315
+
316
+			node->stats_no++;
317
+
318
+			thr->run_node = node->stats_def;
319
+
320
+			return(thr);
321
+		} else {
322
+			node->state = INDEX_COMMIT_WORK;
323
+		}
324
+	}
325
+
326
+	if (node->state == INDEX_COMMIT_WORK) {
327
+
328
+		/* do not commit transaction here for now */
329
+	}
330
+
331
+function_exit:
332
+	trx->error_state = err;
333
+
334
+	if (err == DB_SUCCESS) {
335
+	} else {
336
+		return(NULL);
337
+	}
338
+
148.1.3 by Oleg Tsarev
port patches to 5.5.15
339
+	thr->run_node = que_node_get_parent(node);
340
+
341
+	return(thr);
342
+}
343
+
344
+/****************************************************************//**
345
 Creates the foreign key constraints system tables inside InnoDB
346
 at database creation or database start if they are not found or are
347
 not of the right form.
348
--- a/storage/innobase/dict/dict0dict.c
349
+++ b/storage/innobase/dict/dict0dict.c
118 by kinoyasu
port Yasufumi patches to 5.5.13
350
@@ -755,7 +755,7 @@
24 by Yasufumi Kinoshita
port Yasufumi's patches to 5.5.8
351
 		print an error message and return without doing
352
 		anything. */
353
 		dict_update_statistics(table, TRUE /* only update stats
354
-				       if they have not been initialized */);
355
+				       if they have not been initialized */, FALSE);
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
356
 	}
357
 
24 by Yasufumi Kinoshita
port Yasufumi's patches to 5.5.8
358
 	return(table);
136.3.2 by Yasufumi Kinoshita
Yasufumi patches are ported to 5.5.14
359
@@ -4343,6 +4343,295 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
360
 }
361
 
362
 /*********************************************************************//**
363
+functions to use SYS_STATS system table. */
364
+static
365
+ibool
366
+dict_reload_statistics(
367
+/*===================*/
368
+	dict_table_t*	table,
369
+	ulint*		sum_of_index_sizes)
370
+{
371
+	dict_index_t*	index;
372
+	ulint		size;
373
+	mem_heap_t*	heap;
374
+
375
+	index = dict_table_get_first_index(table);
376
+
377
+	if (index == NULL) {
378
+		/* Table definition is corrupt */
379
+
380
+		return(FALSE);
381
+	}
382
+
383
+	heap = mem_heap_create(1000);
384
+
385
+	while (index) {
386
+		size = btr_get_size(index, BTR_TOTAL_SIZE);
387
+
388
+		index->stat_index_size = size;
389
+
390
+		*sum_of_index_sizes += size;
391
+
392
+		size = btr_get_size(index, BTR_N_LEAF_PAGES);
393
+
394
+		if (size == 0) {
395
+			/* The root node of the tree is a leaf */
396
+			size = 1;
397
+		}
398
+
399
+		index->stat_n_leaf_pages = size;
400
+
401
+/*===========================================*/
402
+{
403
+	dict_table_t*	sys_stats;
404
+	dict_index_t*	sys_index;
405
+	btr_pcur_t	pcur;
406
+	dtuple_t*	tuple;
407
+	dfield_t*	dfield;
408
+	ulint		key_cols;
409
+	ulint		n_cols;
410
+	const rec_t*	rec;
92.1.1 by Yasufumi Kinoshita
fix bug733317
411
+	ulint		n_fields;
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
412
+	const byte*	field;
413
+	ulint		len;
414
+	ib_int64_t*	stat_n_diff_key_vals_tmp;
92.1.1 by Yasufumi Kinoshita
fix bug733317
415
+	ib_int64_t*	stat_n_non_null_key_vals_tmp;
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
416
+	byte*		buf;
417
+	ulint		i;
418
+	mtr_t		mtr;
419
+
420
+	n_cols = dict_index_get_n_unique(index);
421
+	stat_n_diff_key_vals_tmp = mem_heap_zalloc(heap, (n_cols + 1) * sizeof(ib_int64_t));
92.1.1 by Yasufumi Kinoshita
fix bug733317
422
+	stat_n_non_null_key_vals_tmp = mem_heap_zalloc(heap, (n_cols + 1) * sizeof(ib_int64_t));
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
423
+
424
+	sys_stats = dict_sys->sys_stats;
425
+	sys_index = UT_LIST_GET_FIRST(sys_stats->indexes);
426
+	ut_a(!dict_table_is_comp(sys_stats));
427
+
428
+	tuple = dtuple_create(heap, 1);
429
+	dfield = dtuple_get_nth_field(tuple, 0);
430
+
431
+	buf = mem_heap_alloc(heap, 8);
432
+	mach_write_to_8(buf, index->id);
433
+
434
+	dfield_set_data(dfield, buf, 8);
435
+	dict_index_copy_types(tuple, sys_index, 1);
436
+
437
+	mtr_start(&mtr);
438
+
439
+	btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
440
+				  BTR_SEARCH_LEAF, &pcur, &mtr);
441
+	for (i = 0; i <= n_cols; i++) {
442
+		rec = btr_pcur_get_rec(&pcur);
443
+
444
+		if (!btr_pcur_is_on_user_rec(&pcur)
445
+		    || mach_read_from_8(rec_get_nth_field_old(rec, 0, &len))
446
+			!= index->id) {
447
+			/* not found: even 1 if not found should not be alowed */
448
+			fprintf(stderr, "InnoDB: Warning: stats for %s/%s (%lu/%lu)"
58.1.1 by Fred Linhoss
Reworded text strings in patch file print statements.
449
+				        " not found in SYS_STATS\n",
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
450
+					index->table_name, index->name, i, n_cols);
451
+			btr_pcur_close(&pcur);
452
+			mtr_commit(&mtr);
453
+			mem_heap_free(heap);
454
+			return(FALSE);
455
+		}
456
+
457
+		if (rec_get_deleted_flag(rec, 0)) {
92.1.1 by Yasufumi Kinoshita
fix bug733317
458
+			/* don't count */
459
+			i--;
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
460
+			goto next_rec;
461
+		}
462
+
92.1.1 by Yasufumi Kinoshita
fix bug733317
463
+		n_fields = rec_get_n_fields_old(rec);
464
+
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
465
+		field = rec_get_nth_field_old(rec, 1, &len);
466
+		ut_a(len == 4);
467
+
468
+		key_cols = mach_read_from_4(field);
469
+
470
+		ut_a(i == key_cols);
471
+
472
+		field = rec_get_nth_field_old(rec, DICT_SYS_STATS_DIFF_VALS_FIELD, &len);
473
+		ut_a(len == 8);
474
+
475
+		stat_n_diff_key_vals_tmp[i] = mach_read_from_8(field);
92.1.1 by Yasufumi Kinoshita
fix bug733317
476
+
477
+		if (n_fields > DICT_SYS_STATS_NON_NULL_VALS_FIELD) {
478
+			field = rec_get_nth_field_old(rec, DICT_SYS_STATS_NON_NULL_VALS_FIELD, &len);
479
+			ut_a(len == 8);
480
+
481
+			stat_n_non_null_key_vals_tmp[i] = mach_read_from_8(field);
482
+		} else {
483
+			/* not enough fields: should be older */
484
+			fprintf(stderr, "InnoDB: Notice: stats for %s/%s (%lu/%lu)"
485
+					" in SYS_STATS seems older format. "
486
+					"Please execute ANALYZE TABLE for it.\n",
487
+					index->table_name, index->name, i, n_cols);
488
+
489
+			stat_n_non_null_key_vals_tmp[i] = ((ib_int64_t)(-1));
490
+		}
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
491
+next_rec:
492
+		btr_pcur_move_to_next_user_rec(&pcur, &mtr);
493
+	}
494
+
495
+	btr_pcur_close(&pcur);
496
+	mtr_commit(&mtr);
497
+
498
+	for (i = 0; i <= n_cols; i++) {
499
+		index->stat_n_diff_key_vals[i] = stat_n_diff_key_vals_tmp[i];
92.1.1 by Yasufumi Kinoshita
fix bug733317
500
+		if (stat_n_non_null_key_vals_tmp[i] == ((ib_int64_t)(-1))) {
501
+			/* approximate value */
502
+			index->stat_n_non_null_key_vals[i] = stat_n_diff_key_vals_tmp[n_cols];
503
+		} else {
504
+			index->stat_n_non_null_key_vals[i] = stat_n_non_null_key_vals_tmp[i];
505
+		}
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
506
+	}
507
+}
508
+/*===========================================*/
509
+
510
+		index = dict_table_get_next_index(index);
511
+	}
512
+
513
+	mem_heap_free(heap);
514
+	return(TRUE);
515
+}
516
+
517
+static
518
+void
519
+dict_store_statistics(
520
+/*==================*/
521
+	dict_table_t*	table)
522
+{
523
+	dict_index_t*	index;
524
+	mem_heap_t*	heap;
525
+
526
+	index = dict_table_get_first_index(table);
527
+
528
+	ut_a(index);
529
+
530
+	heap = mem_heap_create(1000);
531
+
532
+	while (index) {
533
+/*===========================================*/
534
+{
535
+	dict_table_t*	sys_stats;
536
+	dict_index_t*	sys_index;
537
+	btr_pcur_t	pcur;
538
+	dtuple_t*	tuple;
539
+	dfield_t*	dfield;
540
+	ulint		key_cols;
541
+	ulint		n_cols;
542
+	ulint		rests;
543
+	const rec_t*	rec;
92.1.1 by Yasufumi Kinoshita
fix bug733317
544
+	ulint		n_fields;
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
545
+	const byte*	field;
546
+	ulint		len;
547
+	ib_int64_t*	stat_n_diff_key_vals_tmp;
92.1.1 by Yasufumi Kinoshita
fix bug733317
548
+	ib_int64_t*	stat_n_non_null_key_vals_tmp;
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
549
+	byte*		buf;
550
+	ulint		i;
551
+	mtr_t		mtr;
552
+
553
+	n_cols = dict_index_get_n_unique(index);
554
+	stat_n_diff_key_vals_tmp = mem_heap_zalloc(heap, (n_cols + 1) * sizeof(ib_int64_t));
92.1.1 by Yasufumi Kinoshita
fix bug733317
555
+	stat_n_non_null_key_vals_tmp = mem_heap_zalloc(heap, (n_cols + 1) * sizeof(ib_int64_t));
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
556
+
557
+	for (i = 0; i <= n_cols; i++) {
558
+		stat_n_diff_key_vals_tmp[i] = index->stat_n_diff_key_vals[i];
92.1.1 by Yasufumi Kinoshita
fix bug733317
559
+		stat_n_non_null_key_vals_tmp[i] = index->stat_n_non_null_key_vals[i];
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
560
+	}
561
+
562
+	sys_stats = dict_sys->sys_stats;
563
+	sys_index = UT_LIST_GET_FIRST(sys_stats->indexes);
564
+	ut_a(!dict_table_is_comp(sys_stats));
565
+
566
+	tuple = dtuple_create(heap, 1);
567
+	dfield = dtuple_get_nth_field(tuple, 0);
568
+
569
+	buf = mem_heap_alloc(heap, 8);
570
+	mach_write_to_8(buf, index->id);
571
+
572
+	dfield_set_data(dfield, buf, 8);
573
+	dict_index_copy_types(tuple, sys_index, 1);
574
+
575
+	mtr_start(&mtr);
576
+
577
+	btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
578
+				  BTR_MODIFY_LEAF, &pcur, &mtr);
579
+	rests = n_cols + 1;
580
+	for (i = 0; i <= n_cols; i++) {
581
+		rec = btr_pcur_get_rec(&pcur);
582
+
583
+		if (!btr_pcur_is_on_user_rec(&pcur)
584
+		    || mach_read_from_8(rec_get_nth_field_old(rec, 0, &len))
585
+			!= index->id) {
586
+			/* not found */
69 by kinoyasu
fix potential problem about SYS_STATS
587
+
588
+
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
589
+			break;
590
+		}
591
+
111.4.1 by kinoyasu
fix bug684829 and bug791092
592
+		btr_pcur_store_position(&pcur, &mtr);
593
+
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
594
+		if (rec_get_deleted_flag(rec, 0)) {
92.1.1 by Yasufumi Kinoshita
fix bug733317
595
+			/* don't count */
596
+			i--;
597
+			goto next_rec;
598
+		}
599
+
600
+		n_fields = rec_get_n_fields_old(rec);
601
+
602
+		if (n_fields <= DICT_SYS_STATS_NON_NULL_VALS_FIELD) {
603
+			/* not update for the older smaller format */
604
+			fprintf(stderr, "InnoDB: Notice: stats for %s/%s (%lu/%lu)"
605
+					" in SYS_STATS seems older format. Please ANALYZE TABLE it.\n",
606
+					index->table_name, index->name, i, n_cols);
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
607
+			goto next_rec;
608
+		}
609
+
610
+		field = rec_get_nth_field_old(rec, 1, &len);
611
+		ut_a(len == 4);
612
+
613
+		key_cols = mach_read_from_4(field);
614
+
615
+		field = rec_get_nth_field_old(rec, DICT_SYS_STATS_DIFF_VALS_FIELD, &len);
616
+		ut_a(len == 8);
617
+
618
+		mlog_write_ull((byte*)field, stat_n_diff_key_vals_tmp[key_cols], &mtr);
619
+
92.1.1 by Yasufumi Kinoshita
fix bug733317
620
+		field = rec_get_nth_field_old(rec, DICT_SYS_STATS_NON_NULL_VALS_FIELD, &len);
621
+		ut_a(len == 8);
622
+
623
+		mlog_write_ull((byte*)field, stat_n_non_null_key_vals_tmp[key_cols], &mtr);
624
+
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
625
+		rests--;
626
+
627
+next_rec:
111.4.1 by kinoyasu
fix bug684829 and bug791092
628
+		mtr_commit(&mtr);
629
+		mtr_start(&mtr);
630
+		btr_pcur_restore_position(BTR_MODIFY_LEAF, &pcur, &mtr);
631
+
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
632
+		btr_pcur_move_to_next_user_rec(&pcur, &mtr);
633
+	}
634
+	btr_pcur_close(&pcur);
635
+	mtr_commit(&mtr);
636
+
637
+	if (rests) {
638
+		fprintf(stderr, "InnoDB: Warning: failed to store %lu stats entries"
639
+				" of %s/%s to SYS_STATS system table.\n",
640
+				rests, index->table_name, index->name);
641
+	}
642
+}
643
+/*===========================================*/
644
+
645
+		index = dict_table_get_next_index(index);
646
+	}
647
+
648
+	mem_heap_free(heap);
649
+}
650
+
651
+/*********************************************************************//**
652
 Calculates new estimates for table and index statistics. The statistics
653
 are used in query optimization. */
654
 UNIV_INTERN
136.3.2 by Yasufumi Kinoshita
Yasufumi patches are ported to 5.5.14
655
@@ -4350,10 +4639,11 @@
24 by Yasufumi Kinoshita
port Yasufumi's patches to 5.5.8
656
 dict_update_statistics(
657
 /*===================*/
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
658
 	dict_table_t*	table,		/*!< in/out: table */
24 by Yasufumi Kinoshita
port Yasufumi's patches to 5.5.8
659
-	ibool		only_calc_if_missing_stats)/*!< in: only
660
+	ibool		only_calc_if_missing_stats,/*!< in: only
661
 					update/recalc the stats if they have
662
 					not been initialized yet, otherwise
663
 					do nothing */
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
664
+	ibool		sync)		/*!< in: TRUE if must update SYS_STATS */
665
 {
666
 	dict_index_t*	index;
667
 	ulint		sum_of_index_sizes	= 0;
136.3.2 by Yasufumi Kinoshita
Yasufumi patches are ported to 5.5.14
668
@@ -4370,6 +4660,27 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
669
 		return;
670
 	}
671
 
672
+	if (srv_use_sys_stats_table && !((table->flags >> DICT_TF2_SHIFT) & DICT_TF2_TEMPORARY) && !sync) {
24 by Yasufumi Kinoshita
port Yasufumi's patches to 5.5.8
673
+		dict_table_stats_lock(table, RW_X_LATCH);
674
+
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
675
+		/* reload statistics from SYS_STATS table */
676
+		if (dict_reload_statistics(table, &sum_of_index_sizes)) {
677
+			/* success */
678
+#ifdef UNIV_DEBUG
60.1.1 by Fred Linhoss
Reworded text strings in patch file print statements
679
+			fprintf(stderr, "InnoDB: DEBUG: reload_statistics succeeded for %s.\n",
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
680
+					table->name);
681
+#endif
682
+			goto end;
683
+		}
24 by Yasufumi Kinoshita
port Yasufumi's patches to 5.5.8
684
+
685
+		dict_table_stats_unlock(table, RW_X_LATCH);
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
686
+	}
687
+#ifdef UNIV_DEBUG
688
+	fprintf(stderr, "InnoDB: DEBUG: update_statistics for %s.\n",
689
+			table->name);
690
+#endif
691
+	sum_of_index_sizes = 0;
692
+
693
 	/* Find out the sizes of the indexes and how many different values
694
 	for the key they approximately have */
695
 
136.3.2 by Yasufumi Kinoshita
Yasufumi patches are ported to 5.5.14
696
@@ -4434,6 +4745,11 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
697
 		index = dict_table_get_next_index(index);
698
 	} while (index);
699
 
700
+	if (srv_use_sys_stats_table && !((table->flags >> DICT_TF2_SHIFT) & DICT_TF2_TEMPORARY)) {
701
+		/* store statistics to SYS_STATS table */
702
+		dict_store_statistics(table);
703
+	}
704
+end:
705
 	index = dict_table_get_first_index(table);
706
 
24 by Yasufumi Kinoshita
port Yasufumi's patches to 5.5.8
707
 	table->stat_n_rows = index->stat_n_diff_key_vals[
136.3.2 by Yasufumi Kinoshita
Yasufumi patches are ported to 5.5.14
708
@@ -4451,6 +4767,78 @@
92.1.1 by Yasufumi Kinoshita
fix bug733317
709
 	dict_table_stats_unlock(table, RW_X_LATCH);
710
 }
711
 
712
+/*********************************************************************//**
713
+*/
714
+UNIV_INTERN
715
+ibool
716
+dict_is_older_statistics(
717
+/*=====================*/
718
+	dict_index_t*	index)
719
+{
720
+	mem_heap_t*	heap;
721
+	dict_table_t*	sys_stats;
722
+	dict_index_t*	sys_index;
723
+	btr_pcur_t	pcur;
724
+	dtuple_t*	tuple;
725
+	dfield_t*	dfield;
726
+	const rec_t*	rec;
727
+	ulint		n_fields;
728
+	ulint		len;
729
+	byte*		buf;
730
+	mtr_t		mtr;
731
+
732
+	heap = mem_heap_create(100);
733
+
734
+	sys_stats = dict_sys->sys_stats;
735
+	sys_index = UT_LIST_GET_FIRST(sys_stats->indexes);
736
+	ut_a(!dict_table_is_comp(sys_stats));
737
+
738
+	tuple = dtuple_create(heap, 1);
739
+	dfield = dtuple_get_nth_field(tuple, 0);
740
+
741
+	buf = mem_heap_alloc(heap, 8);
742
+	mach_write_to_8(buf, index->id);
743
+
744
+	dfield_set_data(dfield, buf, 8);
745
+	dict_index_copy_types(tuple, sys_index, 1);
746
+
747
+	mtr_start(&mtr);
748
+
749
+	btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
750
+				  BTR_SEARCH_LEAF, &pcur, &mtr);
751
+
752
+next_rec:
753
+	rec = btr_pcur_get_rec(&pcur);
754
+
755
+	if (!btr_pcur_is_on_user_rec(&pcur)
756
+	    || mach_read_from_8(rec_get_nth_field_old(rec, 0, &len))
757
+		!= index->id) {
758
+		/* not found */
759
+		btr_pcur_close(&pcur);
760
+		mtr_commit(&mtr);
761
+		mem_heap_free(heap);
762
+		/* no statistics == not older statistics */
763
+		return(FALSE);
764
+	}
765
+
766
+	if (rec_get_deleted_flag(rec, 0)) {
767
+		btr_pcur_move_to_next_user_rec(&pcur, &mtr);
768
+		goto next_rec;
769
+	}
770
+
771
+	n_fields = rec_get_n_fields_old(rec);
772
+
773
+	btr_pcur_close(&pcur);
774
+	mtr_commit(&mtr);
775
+	mem_heap_free(heap);
776
+
777
+	if (n_fields > DICT_SYS_STATS_NON_NULL_VALS_FIELD) {
778
+		return(FALSE);
779
+	} else {
780
+		return(TRUE);
781
+	}
782
+}
783
+
784
 /**********************************************************************//**
785
 Prints info of a foreign key constraint. */
786
 static
136.3.2 by Yasufumi Kinoshita
Yasufumi patches are ported to 5.5.14
787
@@ -4528,7 +4916,8 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
788
 
789
 	ut_ad(mutex_own(&(dict_sys->mutex)));
790
 
24 by Yasufumi Kinoshita
port Yasufumi's patches to 5.5.8
791
-	dict_update_statistics(table, FALSE /* update even if initialized */);
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
792
+	if (srv_stats_auto_update)
24 by Yasufumi Kinoshita
port Yasufumi's patches to 5.5.8
793
+		dict_update_statistics(table, FALSE /* update even if initialized */, FALSE);
794
 
795
 	dict_table_stats_lock(table, RW_S_LATCH);
796
 
148.1.3 by Oleg Tsarev
port patches to 5.5.15
797
--- a/storage/innobase/dict/dict0load.c
798
+++ b/storage/innobase/dict/dict0load.c
72 by kinoyasu
port Yasufumi patches to 5.5.9
799
@@ -50,7 +50,8 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
800
 	"SYS_COLUMNS",
801
 	"SYS_FIELDS",
802
 	"SYS_FOREIGN",
803
-	"SYS_FOREIGN_COLS"
804
+	"SYS_FOREIGN_COLS",
805
+	"SYS_STATS"
806
 };
807
 /****************************************************************//**
808
 Compare the name of an index column.
72 by kinoyasu
port Yasufumi patches to 5.5.9
809
@@ -343,12 +344,13 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
810
 	}
811
 
812
 	if ((status & DICT_TABLE_UPDATE_STATS)
813
+	    && srv_stats_auto_update
814
 	    && dict_table_get_first_index(*table)) {
815
 
816
 		/* Update statistics if DICT_TABLE_UPDATE_STATS
817
 		is set */
24 by Yasufumi Kinoshita
port Yasufumi's patches to 5.5.8
818
 		dict_update_statistics(*table, FALSE /* update even if
819
-				       initialized */);
820
+				       initialized */, FALSE);
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
821
 	}
822
 
823
 	return(NULL);
92.1.1 by Yasufumi Kinoshita
fix bug733317
824
@@ -582,6 +584,75 @@
72 by kinoyasu
port Yasufumi patches to 5.5.9
825
 //#endif  /* FOREIGN_NOT_USED */
59 by kinoyasu
fix bug635399 and bug689450: change about innodb_adaptive_checkpoint and innodb_flush_log_at_trx_commit_session
826
 
72 by kinoyasu
port Yasufumi patches to 5.5.9
827
 /********************************************************************//**
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
828
+This function parses a SYS_STATS record and extract necessary
829
+information from the record and return to caller.
830
+@return error message, or NULL on success */
831
+UNIV_INTERN
832
+const char*
833
+dict_process_sys_stats_rec(
834
+/*=============================*/
65 by Yasufumi Kinoshita
eliminate warnings/build problems from XtraDB
835
+	mem_heap_t*	heap __attribute__((unused)),		/*!< in/out: heap memory */
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
836
+	const rec_t*	rec,		/*!< in: current SYS_STATS rec */
837
+	index_id_t*	index_id,	/*!< out: INDEX_ID */
838
+	ulint*		key_cols,	/*!< out: KEY_COLS */
92.1.1 by Yasufumi Kinoshita
fix bug733317
839
+	ib_uint64_t*	diff_vals,	/*!< out: DIFF_VALS */
840
+	ib_uint64_t*	non_null_vals)	/*!< out: NON_NULL_VALS */
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
841
+{
842
+	ulint		len;
843
+	const byte*	field;
92.1.1 by Yasufumi Kinoshita
fix bug733317
844
+	ulint		n_fields;
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
845
+
846
+	if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
847
+		return("delete-marked record in SYS_STATS");
848
+	}
849
+
92.1.1 by Yasufumi Kinoshita
fix bug733317
850
+	n_fields = rec_get_n_fields_old(rec);
851
+
852
+	if (UNIV_UNLIKELY(n_fields < 5)) {
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
853
+		return("wrong number of columns in SYS_STATS record");
854
+	}
855
+
856
+	field = rec_get_nth_field_old(rec, 0/*INDEX_ID*/, &len);
857
+	if (UNIV_UNLIKELY(len != 8)) {
858
+err_len:
859
+		return("incorrect column length in SYS_STATS");
860
+	}
861
+	*index_id = mach_read_from_8(field);
862
+
863
+	field = rec_get_nth_field_old(rec, 1/*KEY_COLS*/, &len);
864
+	if (UNIV_UNLIKELY(len != 4)) {
865
+		goto err_len;
866
+	}
867
+	*key_cols = mach_read_from_4(field);
868
+
869
+	rec_get_nth_field_offs_old(rec, 2/*DB_TRX_ID*/, &len);
870
+	if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
871
+		goto err_len;
872
+	}
873
+	rec_get_nth_field_offs_old(rec, 3/*DB_ROLL_PTR*/, &len);
874
+	if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
875
+		goto err_len;
876
+	}
877
+
878
+	field = rec_get_nth_field_old(rec, 4/*DIFF_VALS*/, &len);
879
+	if (UNIV_UNLIKELY(len != 8)) {
880
+		goto err_len;
881
+	}
882
+	*diff_vals = mach_read_from_8(field);
883
+
92.1.1 by Yasufumi Kinoshita
fix bug733317
884
+	if (n_fields < 6) {
885
+		*non_null_vals = ((ib_uint64_t)(-1));
886
+	} else {
887
+		field = rec_get_nth_field_old(rec, 5/*NON_NULL_VALS*/, &len);
888
+		if (UNIV_UNLIKELY(len != 8)) {
889
+			goto err_len;
890
+		}
891
+		*non_null_vals = mach_read_from_8(field);
892
+	}
893
+
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
894
+	return(NULL);
895
+}
72 by kinoyasu
port Yasufumi patches to 5.5.9
896
+/********************************************************************//**
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
897
 Determine the flags of a table described in SYS_TABLES.
898
 @return compressed page size in kilobytes; or 0 if the tablespace is
72 by kinoyasu
port Yasufumi patches to 5.5.9
899
 uncompressed, ULINT_UNDEFINED on error */
148.1.3 by Oleg Tsarev
port patches to 5.5.15
900
--- a/storage/innobase/handler/ha_innodb.cc
901
+++ b/storage/innobase/handler/ha_innodb.cc
136.3.2 by Yasufumi Kinoshita
Yasufumi patches are ported to 5.5.14
902
@@ -188,6 +188,7 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
903
 static my_bool	innobase_create_status_file		= FALSE;
904
 static my_bool	innobase_stats_on_metadata		= TRUE;
136.3.2 by Yasufumi Kinoshita
Yasufumi patches are ported to 5.5.14
905
 static my_bool	innobase_large_prefix			= FALSE;
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
906
+static my_bool	innobase_use_sys_stats_table		= FALSE;
907
 
908
 
909
 static char*	internal_innobase_data_file_path	= NULL;
148.1.1 by kinoyasu
Yasufumi patches are ported to 5.5.15
910
@@ -2439,6 +2440,8 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
911
 		goto error;
912
 	}
913
 
914
+	srv_use_sys_stats_table = (ibool) innobase_use_sys_stats_table;
915
+
916
 	/* -------------- Log files ---------------------------*/
917
 
918
 	/* The default dir for log files is the datadir of MySQL */
148.1.1 by kinoyasu
Yasufumi patches are ported to 5.5.15
919
@@ -5247,6 +5250,10 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
920
 
921
 	error = row_insert_for_mysql((byte*) record, prebuilt);
922
 
923
+#ifdef EXTENDED_FOR_USERSTAT
924
+	if (error == DB_SUCCESS) rows_changed++;
925
+#endif
926
+
927
 	/* Handle duplicate key errors */
928
 	if (auto_inc_used) {
929
 		ulint		err;
148.1.1 by kinoyasu
Yasufumi patches are ported to 5.5.15
930
@@ -5583,6 +5590,10 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
931
 		}
932
 	}
933
 
934
+#ifdef EXTENDED_FOR_USERSTAT
935
+	if (error == DB_SUCCESS) rows_changed++;
936
+#endif
937
+
938
 	innodb_srv_conc_exit_innodb(trx);
939
 
940
 	error = convert_error_code_to_mysql(error,
148.1.1 by kinoyasu
Yasufumi patches are ported to 5.5.15
941
@@ -5636,6 +5647,10 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
942
 
943
 	error = row_update_for_mysql((byte*) record, prebuilt);
944
 
945
+#ifdef EXTENDED_FOR_USERSTAT
946
+	if (error == DB_SUCCESS) rows_changed++;
947
+#endif
948
+
949
 	innodb_srv_conc_exit_innodb(trx);
950
 
951
 	error = convert_error_code_to_mysql(
148.1.1 by kinoyasu
Yasufumi patches are ported to 5.5.15
952
@@ -5954,6 +5969,11 @@
68 by kinoyasu
fix bug602047
953
 	case DB_SUCCESS:
954
 		error = 0;
955
 		table->status = 0;
956
+#ifdef EXTENDED_FOR_USERSTAT
957
+		rows_read++;
136.1.4 by Laurynas Biveinis
Fixes LP bug #766266: the compiler warning:
958
+		if (active_index < MAX_KEY)
68 by kinoyasu
fix bug602047
959
+			index_rows_read[active_index]++;
960
+#endif
961
 		break;
962
 	case DB_RECORD_NOT_FOUND:
963
 		error = HA_ERR_KEY_NOT_FOUND;
148.1.1 by kinoyasu
Yasufumi patches are ported to 5.5.15
964
@@ -6163,6 +6183,11 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
965
 	case DB_SUCCESS:
966
 		error = 0;
967
 		table->status = 0;
968
+#ifdef EXTENDED_FOR_USERSTAT
969
+		rows_read++;
136.1.4 by Laurynas Biveinis
Fixes LP bug #766266: the compiler warning:
970
+		if (active_index < MAX_KEY)
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
971
+			index_rows_read[active_index]++;
972
+#endif
973
 		break;
974
 	case DB_RECORD_NOT_FOUND:
975
 		error = HA_ERR_END_OF_FILE;
148.1.1 by kinoyasu
Yasufumi patches are ported to 5.5.15
976
@@ -8105,11 +8130,35 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
977
 			/* In sql_show we call with this flag: update
978
 			then statistics so that they are up-to-date */
979
 
980
+			if (srv_use_sys_stats_table && !((ib_table->flags >> DICT_TF2_SHIFT) & DICT_TF2_TEMPORARY)
24 by Yasufumi Kinoshita
port Yasufumi's patches to 5.5.8
981
+			    && called_from_analyze) {
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
982
+				/* If the indexes on the table don't have enough rows in SYS_STATS system table, */
983
+				/* they need to be created. */
984
+				dict_index_t*	index;
985
+
986
+				prebuilt->trx->op_info = "confirming rows of SYS_STATS to store statistics";
987
+
988
+				ut_a(prebuilt->trx->conc_state == TRX_NOT_STARTED);
989
+
990
+				for (index = dict_table_get_first_index(ib_table);
991
+				     index != NULL;
992
+				     index = dict_table_get_next_index(index)) {
92.1.1 by Yasufumi Kinoshita
fix bug733317
993
+					if (dict_is_older_statistics(index)) {
994
+						row_delete_stats_for_mysql(index, prebuilt->trx);
995
+						innobase_commit_low(prebuilt->trx);
996
+					}
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
997
+					row_insert_stats_for_mysql(index, prebuilt->trx);
998
+					innobase_commit_low(prebuilt->trx);
999
+				}
1000
+
1001
+				ut_a(prebuilt->trx->conc_state == TRX_NOT_STARTED);
1002
+			}
1003
+
1004
 			prebuilt->trx->op_info = "updating table statistics";
1005
 
24 by Yasufumi Kinoshita
port Yasufumi's patches to 5.5.8
1006
 			dict_update_statistics(ib_table,
1007
 					       FALSE /* update even if stats
1008
-						     are initialized */);
1009
+						     are initialized */, called_from_analyze);
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1010
 
1011
 			prebuilt->trx->op_info = "returning various info to MySQL";
1012
 		}
148.1.1 by kinoyasu
Yasufumi patches are ported to 5.5.15
1013
@@ -8187,7 +8236,7 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1014
 		are asked by MySQL to avoid locking. Another reason to
1015
 		avoid the call is that it uses quite a lot of CPU.
1016
 		See Bug#38185. */
72 by kinoyasu
port Yasufumi patches to 5.5.9
1017
-		if (flag & HA_STATUS_NO_LOCK
1018
+		if (flag & HA_STATUS_NO_LOCK || !srv_stats_update_need_lock
1019
 		    || !(flag & HA_STATUS_VARIABLE_EXTRA)) {
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1020
 			/* We do not update delete_length if no
1021
 			locking is requested so the "old" value can
148.1.1 by kinoyasu
Yasufumi patches are ported to 5.5.15
1022
@@ -11401,6 +11450,26 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1023
   "The number of index pages to sample when calculating statistics (default 8)",
1024
   NULL, NULL, 8, 1, ~0ULL, 0);
1025
 
1026
+static MYSQL_SYSVAR_ULONG(stats_auto_update, srv_stats_auto_update,
1027
+  PLUGIN_VAR_RQCMDARG,
1028
+  "Enable/Disable InnoDB's auto update statistics of indexes. "
1029
+  "(except for ANALYZE TABLE command) 0:disable 1:enable",
1030
+  NULL, NULL, 1, 0, 1, 0);
1031
+
1032
+static MYSQL_SYSVAR_ULONG(stats_update_need_lock, srv_stats_update_need_lock,
1033
+  PLUGIN_VAR_RQCMDARG,
1034
+  "Enable/Disable InnoDB's update statistics which needs to lock dictionary. "
1035
+  "e.g. Data_free.",
1036
+  NULL, NULL, 1, 0, 1, 0);
1037
+
1038
+static MYSQL_SYSVAR_BOOL(use_sys_stats_table, innobase_use_sys_stats_table,
1039
+  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
1040
+  "Enable to use SYS_STATS system table to store statistics statically, "
1041
+  "And avoids to calculate statistics at every first open of the tables. "
1042
+  "This option may make the opportunities of update statistics less. "
1043
+  "So you should use ANALYZE TABLE command intentionally.",
1044
+  NULL, NULL, FALSE);
1045
+
1046
 static MYSQL_SYSVAR_BOOL(adaptive_hash_index, btr_search_enabled,
1047
   PLUGIN_VAR_OPCMDARG,
1048
   "Enable InnoDB adaptive hash index (enabled by default).  "
148.1.1 by kinoyasu
Yasufumi patches are ported to 5.5.15
1049
@@ -11727,6 +11796,9 @@
88 by Yasufumi Kinoshita
fix bug721611 (rename variables)
1050
   MYSQL_SYSVAR(recovery_update_relay_log),
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1051
   MYSQL_SYSVAR(rollback_on_timeout),
1052
   MYSQL_SYSVAR(stats_on_metadata),
1053
+  MYSQL_SYSVAR(stats_auto_update),
1054
+  MYSQL_SYSVAR(stats_update_need_lock),
1055
+  MYSQL_SYSVAR(use_sys_stats_table),
1056
   MYSQL_SYSVAR(stats_sample_pages),
1057
   MYSQL_SYSVAR(adaptive_hash_index),
90 by Yasufumi Kinoshita
Yasufumi patches are ported to 5.5.10; Note: option innodb_stats_method was removed from innodb_stats.patch, because implemented officially. And, bug733317 should be fixed before release
1058
   MYSQL_SYSVAR(stats_method),
148.1.1 by kinoyasu
Yasufumi patches are ported to 5.5.15
1059
@@ -11796,7 +11868,10 @@
35 by Yasufumi Kinoshita
fix wrongness/contention about userstat.patch; remove innodb_show_enhancements.patch
1060
 i_s_innodb_sys_columns,
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1061
 i_s_innodb_sys_fields,
1062
 i_s_innodb_sys_foreign,
35 by Yasufumi Kinoshita
fix wrongness/contention about userstat.patch; remove innodb_show_enhancements.patch
1063
-i_s_innodb_sys_foreign_cols
1064
+i_s_innodb_sys_foreign_cols,
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1065
+i_s_innodb_sys_stats,
1066
+i_s_innodb_table_stats,
35 by Yasufumi Kinoshita
fix wrongness/contention about userstat.patch; remove innodb_show_enhancements.patch
1067
+i_s_innodb_index_stats
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1068
 mysql_declare_plugin_end;
1069
 
35 by Yasufumi Kinoshita
fix wrongness/contention about userstat.patch; remove innodb_show_enhancements.patch
1070
 /** @brief Initialize the default value of innodb_commit_concurrency.
148.1.3 by Oleg Tsarev
port patches to 5.5.15
1071
--- a/storage/innobase/handler/i_s.cc
1072
+++ b/storage/innobase/handler/i_s.cc
35 by Yasufumi Kinoshita
fix wrongness/contention about userstat.patch; remove innodb_show_enhancements.patch
1073
@@ -49,6 +49,7 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1074
 #include "trx0trx.h" /* for TRX_QUE_STATE_STR_MAX_LEN */
1075
 #include "trx0rseg.h" /* for trx_rseg_struct */
1076
 #include "trx0sys.h" /* for trx_sys */
1077
+#include "dict0dict.h" /* for dict_sys */
1078
 }
1079
 
109 by kinoyasu
port Yasufumi patches to 5.5.12
1080
 #define OK(expr)		\
1081
@@ -3455,6 +3456,221 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1082
 	STRUCT_FLD(__reserved1, NULL)
1083
 };
1084
 
1085
+/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_sys_stats */
1086
+static ST_FIELD_INFO	innodb_sys_stats_fields_info[] =
1087
+{
1088
+#define SYS_STATS_INDEX_ID	0
1089
+	{STRUCT_FLD(field_name,		"INDEX_ID"),
1090
+	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
1091
+	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
1092
+	 STRUCT_FLD(value,		0),
1093
+	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
1094
+	 STRUCT_FLD(old_name,		""),
1095
+	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1096
+
1097
+#define SYS_STATS_KEY_COLS	1
1098
+	{STRUCT_FLD(field_name,		"KEY_COLS"),
1099
+	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
1100
+	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
1101
+	 STRUCT_FLD(value,		0),
1102
+	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
1103
+	 STRUCT_FLD(old_name,		""),
1104
+	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1105
+
1106
+#define SYS_STATS_DIFF_VALS	2
1107
+	{STRUCT_FLD(field_name,		"DIFF_VALS"),
1108
+	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
1109
+	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
1110
+	 STRUCT_FLD(value,		0),
1111
+	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
1112
+	 STRUCT_FLD(old_name,		""),
1113
+	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1114
+
92.1.1 by Yasufumi Kinoshita
fix bug733317
1115
+#define SYS_STATS_NON_NULL_VALS	3
1116
+	{STRUCT_FLD(field_name,		"NON_NULL_VALS"),
1117
+	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
1118
+	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
1119
+	 STRUCT_FLD(value,		0),
1120
+	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED | MY_I_S_MAYBE_NULL),
1121
+	 STRUCT_FLD(old_name,		""),
1122
+	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1123
+
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1124
+	END_OF_ST_FIELD_INFO
1125
+};
1126
+/**********************************************************************//**
1127
+Function to fill information_schema.innodb_sys_stats
1128
+@return 0 on success */
1129
+static
1130
+int
1131
+i_s_dict_fill_sys_stats(
1132
+/*====================*/
1133
+	THD*		thd,		/*!< in: thread */
1134
+	index_id_t	index_id,	/*!< in: INDEX_ID */
1135
+	ulint		key_cols,	/*!< in: KEY_COLS */
1136
+	ib_uint64_t	diff_vals,	/*!< in: DIFF_VALS */
92.1.1 by Yasufumi Kinoshita
fix bug733317
1137
+	ib_uint64_t	non_null_vals,	/*!< in: NON_NULL_VALS */
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1138
+	TABLE*		table_to_fill)  /*!< in/out: fill this table */
1139
+{
1140
+	Field**		fields;
1141
+
1142
+	DBUG_ENTER("i_s_dict_fill_sys_stats");
1143
+
1144
+	fields = table_to_fill->field;
1145
+
1146
+	OK(fields[SYS_STATS_INDEX_ID]->store(longlong(index_id), TRUE));
1147
+
1148
+	OK(fields[SYS_STATS_KEY_COLS]->store(key_cols));
1149
+
1150
+	OK(fields[SYS_STATS_DIFF_VALS]->store(longlong(diff_vals), TRUE));
1151
+
92.1.1 by Yasufumi Kinoshita
fix bug733317
1152
+	if (non_null_vals == ((ib_uint64_t)(-1))) {
1153
+		fields[SYS_STATS_NON_NULL_VALS]->set_null();
1154
+	} else {
1155
+		OK(fields[SYS_STATS_NON_NULL_VALS]->store(longlong(non_null_vals), TRUE));
1156
+		fields[SYS_STATS_NON_NULL_VALS]->set_notnull();
1157
+	}
1158
+
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1159
+	OK(schema_table_store_record(thd, table_to_fill));
1160
+
1161
+	DBUG_RETURN(0);
1162
+}
1163
+/*******************************************************************//**
1164
+Function to populate INFORMATION_SCHEMA.innodb_sys_stats table.
1165
+@return 0 on success */
1166
+static
1167
+int
1168
+i_s_sys_stats_fill_table(
1169
+/*=====================*/
1170
+	THD*		thd,    /*!< in: thread */
1171
+	TABLE_LIST*	tables, /*!< in/out: tables to fill */
1172
+	COND*		cond)   /*!< in: condition (not used) */
1173
+{
1174
+        btr_pcur_t	pcur;
1175
+	const rec_t*	rec;
1176
+	mem_heap_t*	heap;
1177
+	mtr_t		mtr;
1178
+
1179
+	DBUG_ENTER("i_s_sys_stats_fill_table");
1180
+
1181
+	/* deny access to non-superusers */
1182
+	if (check_global_access(thd, PROCESS_ACL)) {
1183
+                DBUG_RETURN(0);
1184
+	}
1185
+
1186
+        heap = mem_heap_create(1000);
1187
+        mutex_enter(&dict_sys->mutex);
1188
+        mtr_start(&mtr);
1189
+
1190
+	rec = dict_startscan_system(&pcur, &mtr, SYS_STATS);
1191
+
1192
+	while (rec) {
1193
+		const char*	err_msg;
1194
+		index_id_t	index_id;
1195
+		ulint		key_cols;
1196
+		ib_uint64_t	diff_vals;
92.1.1 by Yasufumi Kinoshita
fix bug733317
1197
+		ib_uint64_t	non_null_vals;
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1198
+
1199
+		/* Extract necessary information from a SYS_FOREIGN_COLS row */
1200
+		err_msg = dict_process_sys_stats_rec(
92.1.1 by Yasufumi Kinoshita
fix bug733317
1201
+			heap, rec, &index_id, &key_cols, &diff_vals, &non_null_vals);
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1202
+
1203
+		mtr_commit(&mtr);
1204
+		mutex_exit(&dict_sys->mutex);
1205
+
1206
+		if (!err_msg) {
1207
+			i_s_dict_fill_sys_stats(
92.1.1 by Yasufumi Kinoshita
fix bug733317
1208
+				thd, index_id, key_cols, diff_vals, non_null_vals,
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1209
+				tables->table);
1210
+		} else {
1211
+			push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
1212
+					    ER_CANT_FIND_SYSTEM_REC,
1213
+					    err_msg);
1214
+		}
1215
+
1216
+		mem_heap_empty(heap);
1217
+
1218
+		/* Get the next record */
1219
+		mutex_enter(&dict_sys->mutex);
1220
+		mtr_start(&mtr);
1221
+		rec = dict_getnext_system(&pcur, &mtr);
1222
+	}
1223
+
1224
+	mtr_commit(&mtr);
1225
+	mutex_exit(&dict_sys->mutex);
1226
+	mem_heap_free(heap);
1227
+
1228
+	DBUG_RETURN(0);
1229
+}
1230
+/*******************************************************************//**
1231
+Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_stats
1232
+@return 0 on success */
1233
+static
1234
+int
1235
+innodb_sys_stats_init(
1236
+/*========================*/
1237
+        void*   p)      /*!< in/out: table schema object */
1238
+{
1239
+        ST_SCHEMA_TABLE*        schema;
1240
+
1241
+        DBUG_ENTER("innodb_sys_stats_init");
1242
+
1243
+        schema = (ST_SCHEMA_TABLE*) p;
1244
+
1245
+        schema->fields_info = innodb_sys_stats_fields_info;
1246
+        schema->fill_table = i_s_sys_stats_fill_table;
1247
+
1248
+        DBUG_RETURN(0);
1249
+}
1250
+
1251
+UNIV_INTERN struct st_mysql_plugin	i_s_innodb_sys_stats =
1252
+{
1253
+	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
1254
+	/* int */
1255
+	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
1256
+
1257
+	/* pointer to type-specific plugin descriptor */
1258
+	/* void* */
1259
+	STRUCT_FLD(info, &i_s_info),
1260
+
1261
+	/* plugin name */
1262
+	/* const char* */
1263
+	STRUCT_FLD(name, "INNODB_SYS_STATS"),
1264
+
1265
+	/* plugin author (for SHOW PLUGINS) */
1266
+	/* const char* */
110.1.1 by kinoyasu
fix bug723050
1267
+	STRUCT_FLD(author, "Percona"),
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1268
+
1269
+	/* general descriptive text (for SHOW PLUGINS) */
1270
+	/* const char* */
1271
+	STRUCT_FLD(descr, "XtraDB SYS_STATS table"),
1272
+
1273
+	/* the plugin license (PLUGIN_LICENSE_XXX) */
1274
+	/* int */
1275
+	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
1276
+
1277
+	/* the function to invoke when plugin is loaded */
1278
+	/* int (*)(void*); */
1279
+	STRUCT_FLD(init, innodb_sys_stats_init),
1280
+
1281
+	/* the function to invoke when plugin is unloaded */
1282
+	/* int (*)(void*); */
1283
+	STRUCT_FLD(deinit, i_s_common_deinit),
1284
+
1285
+	/* plugin version (for SHOW PLUGINS) */
1286
+	/* unsigned int */
1287
+	STRUCT_FLD(version, INNODB_VERSION_SHORT),
1288
+
1289
+	/* struct st_mysql_show_var* */
1290
+	STRUCT_FLD(status_vars, NULL),
1291
+
1292
+	/* struct st_mysql_sys_var** */
1293
+	STRUCT_FLD(system_vars, NULL),
1294
+
1295
+	/* reserved for dependency checking */
1296
+	/* void* */
1297
+	STRUCT_FLD(__reserved1, NULL)
1298
+};
1299
+
1300
 /***********************************************************************
1301
 */
1302
 static ST_FIELD_INFO	i_s_innodb_rseg_fields_info[] =
109 by kinoyasu
port Yasufumi patches to 5.5.12
1303
@@ -3617,3 +3833,347 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1304
 	/* void* */
1305
 	STRUCT_FLD(__reserved1, NULL)
1306
 };
1307
+
1308
+/***********************************************************************
1309
+*/
1310
+static ST_FIELD_INFO	i_s_innodb_table_stats_info[] =
1311
+{
1312
+	{STRUCT_FLD(field_name,		"table_schema"),
1313
+	 STRUCT_FLD(field_length,	NAME_LEN),
1314
+	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
1315
+	 STRUCT_FLD(value,		0),
1316
+	 STRUCT_FLD(field_flags,	0),
1317
+	 STRUCT_FLD(old_name,		""),
1318
+	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1319
+
1320
+	{STRUCT_FLD(field_name,		"table_name"),
1321
+	 STRUCT_FLD(field_length,	NAME_LEN),
1322
+	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
1323
+	 STRUCT_FLD(value,		0),
1324
+	 STRUCT_FLD(field_flags,	0),
1325
+	 STRUCT_FLD(old_name,		""),
1326
+	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1327
+
1328
+	{STRUCT_FLD(field_name,		"rows"),
1329
+	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
1330
+	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
1331
+	 STRUCT_FLD(value,		0),
1332
+	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
1333
+	 STRUCT_FLD(old_name,		""),
1334
+	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1335
+
1336
+	{STRUCT_FLD(field_name,		"clust_size"),
1337
+	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
1338
+	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
1339
+	 STRUCT_FLD(value,		0),
1340
+	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
1341
+	 STRUCT_FLD(old_name,		""),
1342
+	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1343
+
1344
+	{STRUCT_FLD(field_name,		"other_size"),
1345
+	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
1346
+	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
1347
+	 STRUCT_FLD(value,		0),
1348
+	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
1349
+	 STRUCT_FLD(old_name,		""),
1350
+	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1351
+
1352
+	{STRUCT_FLD(field_name,		"modified"),
1353
+	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
1354
+	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
1355
+	 STRUCT_FLD(value,		0),
1356
+	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
1357
+	 STRUCT_FLD(old_name,		""),
1358
+	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1359
+
1360
+	END_OF_ST_FIELD_INFO
1361
+};
1362
+
1363
+static ST_FIELD_INFO	i_s_innodb_index_stats_info[] =
1364
+{
1365
+	{STRUCT_FLD(field_name,		"table_schema"),
1366
+	 STRUCT_FLD(field_length,	NAME_LEN),
1367
+	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
1368
+	 STRUCT_FLD(value,		0),
1369
+	 STRUCT_FLD(field_flags,	0),
1370
+	 STRUCT_FLD(old_name,		""),
1371
+	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1372
+
1373
+	{STRUCT_FLD(field_name,		"table_name"),
1374
+	 STRUCT_FLD(field_length,	NAME_LEN),
1375
+	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
1376
+	 STRUCT_FLD(value,		0),
1377
+	 STRUCT_FLD(field_flags,	0),
1378
+	 STRUCT_FLD(old_name,		""),
1379
+	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1380
+
1381
+	{STRUCT_FLD(field_name,		"index_name"),
1382
+	 STRUCT_FLD(field_length,	NAME_LEN),
1383
+	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
1384
+	 STRUCT_FLD(value,		0),
1385
+	 STRUCT_FLD(field_flags,	0),
1386
+	 STRUCT_FLD(old_name,		""),
1387
+	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1388
+
1389
+	{STRUCT_FLD(field_name,		"fields"),
1390
+	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
1391
+	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
1392
+	 STRUCT_FLD(value,		0),
1393
+	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
1394
+	 STRUCT_FLD(old_name,		""),
1395
+	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1396
+
37 by Yasufumi Kinoshita
rename field of innodb_index_stats
1397
+	{STRUCT_FLD(field_name,		"rows_per_key"),
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1398
+	 STRUCT_FLD(field_length,	256),
1399
+	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
1400
+	 STRUCT_FLD(value,		0),
1401
+	 STRUCT_FLD(field_flags,	0),
1402
+	 STRUCT_FLD(old_name,		""),
1403
+	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1404
+
36 by Yasufumi Kinoshita
adjustment for compiler warnings; rename fields of innodb_index_stats
1405
+	{STRUCT_FLD(field_name,		"index_total_pages"),
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1406
+	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
1407
+	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
1408
+	 STRUCT_FLD(value,		0),
1409
+	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
1410
+	 STRUCT_FLD(old_name,		""),
1411
+	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1412
+
36 by Yasufumi Kinoshita
adjustment for compiler warnings; rename fields of innodb_index_stats
1413
+	{STRUCT_FLD(field_name,		"index_leaf_pages"),
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1414
+	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
1415
+	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
1416
+	 STRUCT_FLD(value,		0),
1417
+	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
1418
+	 STRUCT_FLD(old_name,		""),
1419
+	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1420
+
1421
+	END_OF_ST_FIELD_INFO
1422
+};
1423
+
1424
+static
1425
+int
1426
+i_s_innodb_table_stats_fill(
1427
+/*========================*/
1428
+	THD*		thd,
1429
+	TABLE_LIST*	tables,
1430
+	COND*		cond)
1431
+{
1432
+	TABLE*	i_s_table	= (TABLE *) tables->table;
1433
+	int	status	= 0;
1434
+	dict_table_t*	table;
1435
+
1436
+	DBUG_ENTER("i_s_innodb_table_stats_fill");
1437
+
1438
+	/* deny access to non-superusers */
1439
+	if (check_global_access(thd, PROCESS_ACL)) {
1440
+		DBUG_RETURN(0);
1441
+	}
1442
+
1443
+	mutex_enter(&(dict_sys->mutex));
1444
+
1445
+	table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
1446
+
1447
+	while (table) {
1448
+		char	buf[NAME_LEN * 2 + 2];
1449
+		char*	ptr;
1450
+
1451
+		if (table->stat_clustered_index_size == 0) {
1452
+			table = UT_LIST_GET_NEXT(table_LRU, table);
1453
+			continue;
1454
+		}
1455
+
1456
+		buf[NAME_LEN * 2 + 1] = 0;
1457
+		strncpy(buf, table->name, NAME_LEN * 2 + 1);
1458
+		ptr = strchr(buf, '/');
1459
+		if (ptr) {
1460
+			*ptr = '\0';
1461
+			++ptr;
1462
+		} else {
1463
+			ptr = buf;
1464
+		}
1465
+
1466
+		field_store_string(i_s_table->field[0], buf);
1467
+		field_store_string(i_s_table->field[1], ptr);
1468
+		i_s_table->field[2]->store(table->stat_n_rows);
1469
+		i_s_table->field[3]->store(table->stat_clustered_index_size);
1470
+		i_s_table->field[4]->store(table->stat_sum_of_other_index_sizes);
1471
+		i_s_table->field[5]->store(table->stat_modified_counter);
1472
+
1473
+		if (schema_table_store_record(thd, i_s_table)) {
1474
+			status = 1;
1475
+			break;
1476
+		}
1477
+
1478
+		table = UT_LIST_GET_NEXT(table_LRU, table);
1479
+	}
1480
+
1481
+	mutex_exit(&(dict_sys->mutex));
1482
+
1483
+	DBUG_RETURN(status);
1484
+}
1485
+
1486
+static
1487
+int
1488
+i_s_innodb_index_stats_fill(
1489
+/*========================*/
1490
+	THD*		thd,
1491
+	TABLE_LIST*	tables,
1492
+	COND*		cond)
1493
+{
1494
+	TABLE*	i_s_table	= (TABLE *) tables->table;
1495
+	int	status	= 0;
1496
+	dict_table_t*	table;
1497
+	dict_index_t*	index;
1498
+
1499
+	DBUG_ENTER("i_s_innodb_index_stats_fill");
1500
+
1501
+	/* deny access to non-superusers */
1502
+	if (check_global_access(thd, PROCESS_ACL)) {
1503
+		DBUG_RETURN(0);
1504
+	}
1505
+
1506
+	mutex_enter(&(dict_sys->mutex));
1507
+
1508
+	table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
1509
+
1510
+	while (table) {
1511
+		if (table->stat_clustered_index_size == 0) {
1512
+			table = UT_LIST_GET_NEXT(table_LRU, table);
1513
+			continue;
1514
+		}
1515
+
1516
+		ib_int64_t	n_rows = table->stat_n_rows;
1517
+
1518
+		if (n_rows < 0) {
1519
+			n_rows = 0;
1520
+		}
1521
+
1522
+		index = dict_table_get_first_index(table);
1523
+
1524
+		while (index) {
1525
+			char	buff[256+1];
1526
+			char	row_per_keys[256+1];
1527
+			char	buf[NAME_LEN * 2 + 2];
1528
+			char*	ptr;
1529
+			ulint	i;
1530
+
1531
+			buf[NAME_LEN * 2 + 1] = 0;
1532
+			strncpy(buf, table->name, NAME_LEN * 2 + 1);
1533
+			ptr = strchr(buf, '/');
1534
+			if (ptr) {
1535
+				*ptr = '\0';
1536
+				++ptr;
1537
+			} else {
1538
+				ptr = buf;
1539
+			}
1540
+
1541
+			field_store_string(i_s_table->field[0], buf);
1542
+			field_store_string(i_s_table->field[1], ptr);
1543
+			field_store_string(i_s_table->field[2], index->name);
1544
+			i_s_table->field[3]->store(index->n_uniq);
1545
+
1546
+			row_per_keys[0] = '\0';
1547
+
1548
+			/* It is remained optimistic operation still for now */
1549
+			//dict_index_stat_mutex_enter(index);
1550
+			if (index->stat_n_diff_key_vals) {
1551
+				for (i = 1; i <= index->n_uniq; i++) {
1552
+					ib_int64_t	rec_per_key;
1553
+					if (index->stat_n_diff_key_vals[i]) {
1554
+						rec_per_key = n_rows / index->stat_n_diff_key_vals[i];
1555
+					} else {
1556
+						rec_per_key = n_rows;
1557
+					}
1558
+					ut_snprintf(buff, 256, (i == index->n_uniq)?"%llu":"%llu, ",
1559
+						 rec_per_key);
1560
+					strncat(row_per_keys, buff, 256 - strlen(row_per_keys));
1561
+				}
1562
+			}
1563
+			//dict_index_stat_mutex_exit(index);
1564
+
1565
+			field_store_string(i_s_table->field[4], row_per_keys);
1566
+
1567
+			i_s_table->field[5]->store(index->stat_index_size);
1568
+			i_s_table->field[6]->store(index->stat_n_leaf_pages);
1569
+
1570
+			if (schema_table_store_record(thd, i_s_table)) {
1571
+				status = 1;
1572
+				break;
1573
+			}
1574
+
1575
+			index = dict_table_get_next_index(index);
1576
+		}
1577
+
1578
+		if (status == 1) {
1579
+			break;
1580
+		}
1581
+
1582
+		table = UT_LIST_GET_NEXT(table_LRU, table);
1583
+	}
1584
+
1585
+	mutex_exit(&(dict_sys->mutex));
1586
+
1587
+	DBUG_RETURN(status);
1588
+}
1589
+
1590
+static
1591
+int
1592
+i_s_innodb_table_stats_init(
1593
+/*========================*/
1594
+	void*   p)
1595
+{
1596
+	DBUG_ENTER("i_s_innodb_table_stats_init");
1597
+	ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
1598
+
1599
+	schema->fields_info = i_s_innodb_table_stats_info;
1600
+	schema->fill_table = i_s_innodb_table_stats_fill;
1601
+
1602
+	DBUG_RETURN(0);
1603
+}
1604
+
1605
+static
1606
+int
1607
+i_s_innodb_index_stats_init(
1608
+/*========================*/
1609
+	void*	p)
1610
+{
1611
+	DBUG_ENTER("i_s_innodb_index_stats_init");
1612
+	ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
1613
+
1614
+	schema->fields_info = i_s_innodb_index_stats_info;
1615
+	schema->fill_table = i_s_innodb_index_stats_fill;
1616
+
1617
+	DBUG_RETURN(0);
1618
+}
1619
+
1620
+UNIV_INTERN struct st_mysql_plugin	i_s_innodb_table_stats =
1621
+{
1622
+	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
1623
+	STRUCT_FLD(info, &i_s_info),
1624
+	STRUCT_FLD(name, "INNODB_TABLE_STATS"),
110.1.1 by kinoyasu
fix bug723050
1625
+	STRUCT_FLD(author, "Percona"),
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1626
+	STRUCT_FLD(descr, "InnoDB table statistics in memory"),
1627
+	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
1628
+	STRUCT_FLD(init, i_s_innodb_table_stats_init),
1629
+	STRUCT_FLD(deinit, i_s_common_deinit),
1630
+	STRUCT_FLD(version, 0x0100 /* 1.0 */),
1631
+	STRUCT_FLD(status_vars, NULL),
1632
+	STRUCT_FLD(system_vars, NULL),
1633
+	STRUCT_FLD(__reserved1, NULL)
1634
+};
1635
+
1636
+UNIV_INTERN struct st_mysql_plugin	i_s_innodb_index_stats =
1637
+{
1638
+	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
1639
+	STRUCT_FLD(info, &i_s_info),
1640
+	STRUCT_FLD(name, "INNODB_INDEX_STATS"),
110.1.1 by kinoyasu
fix bug723050
1641
+	STRUCT_FLD(author, "Percona"),
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1642
+	STRUCT_FLD(descr, "InnoDB index statistics in memory"),
1643
+	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
1644
+	STRUCT_FLD(init, i_s_innodb_index_stats_init),
1645
+	STRUCT_FLD(deinit, i_s_common_deinit),
1646
+	STRUCT_FLD(version, 0x0100 /* 1.0 */),
1647
+	STRUCT_FLD(status_vars, NULL),
1648
+	STRUCT_FLD(system_vars, NULL),
1649
+	STRUCT_FLD(__reserved1, NULL)
1650
+};
148.1.3 by Oleg Tsarev
port patches to 5.5.15
1651
--- a/storage/innobase/handler/i_s.h
1652
+++ b/storage/innobase/handler/i_s.h
109 by kinoyasu
port Yasufumi patches to 5.5.12
1653
@@ -43,5 +43,8 @@
35 by Yasufumi Kinoshita
fix wrongness/contention about userstat.patch; remove innodb_show_enhancements.patch
1654
 extern struct st_mysql_plugin   i_s_innodb_sys_foreign;
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1655
 extern struct st_mysql_plugin   i_s_innodb_sys_foreign_cols;
35 by Yasufumi Kinoshita
fix wrongness/contention about userstat.patch; remove innodb_show_enhancements.patch
1656
 extern struct st_mysql_plugin	i_s_innodb_rseg;
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1657
+extern struct st_mysql_plugin	i_s_innodb_sys_stats;
1658
+extern struct st_mysql_plugin	i_s_innodb_table_stats;
1659
+extern struct st_mysql_plugin	i_s_innodb_index_stats;
1660
 
1661
 #endif /* i_s_h */
148.1.3 by Oleg Tsarev
port patches to 5.5.15
1662
--- a/storage/innobase/include/dict0boot.h
1663
+++ b/storage/innobase/include/dict0boot.h
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1664
@@ -104,6 +104,7 @@
1665
 #define DICT_COLUMNS_ID		2
1666
 #define DICT_INDEXES_ID		3
1667
 #define DICT_FIELDS_ID		4
1668
+#define DICT_STATS_ID		6
1669
 /* The following is a secondary index on SYS_TABLES */
1670
 #define DICT_TABLE_IDS_ID	5
1671
 
1672
@@ -131,10 +132,13 @@
1673
 #define	DICT_HDR_INDEXES	44	/* Root of the index index tree */
1674
 #define	DICT_HDR_FIELDS		48	/* Root of the index field
1675
 					index tree */
1676
+#define	DICT_HDR_STATS		52	/* Root of the stats tree */
1677
 
1678
 #define DICT_HDR_FSEG_HEADER	56	/* Segment header for the tablespace
1679
 					segment into which the dictionary
1680
 					header is created */
1681
+
1682
+#define	DICT_HDR_XTRADB_MARK	256	/* Flag to distinguish expansion of XtraDB */
1683
 /*-------------------------------------------------------------*/
1684
 
1685
 /* The field number of the page number field in the sys_indexes table
92.1.1 by Yasufumi Kinoshita
fix bug733317
1686
@@ -144,11 +148,16 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1687
 #define DICT_SYS_INDEXES_TYPE_FIELD	 6
1688
 #define DICT_SYS_INDEXES_NAME_FIELD	 4
1689
 
1690
+#define DICT_SYS_STATS_DIFF_VALS_FIELD	 4
92.1.1 by Yasufumi Kinoshita
fix bug733317
1691
+#define DICT_SYS_STATS_NON_NULL_VALS_FIELD	5
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1692
+
1693
 /* When a row id which is zero modulo this number (which must be a power of
1694
 two) is assigned, the field DICT_HDR_ROW_ID on the dictionary header page is
1695
 updated */
1696
 #define DICT_HDR_ROW_ID_WRITE_MARGIN	256
1697
 
1698
+#define DICT_HDR_XTRADB_FLAG		0x5854524144425F31ULL	/* "XTRADB_1" */
1699
+
1700
 #ifndef UNIV_NONINL
1701
 #include "dict0boot.ic"
1702
 #endif
148.1.3 by Oleg Tsarev
port patches to 5.5.15
1703
--- a/storage/innobase/include/dict0crea.h
1704
+++ b/storage/innobase/include/dict0crea.h
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1705
@@ -53,6 +53,14 @@
1706
 	dict_index_t*	index,	/*!< in: index to create, built as a memory data
1707
 				structure */
1708
 	mem_heap_t*	heap);	/*!< in: heap where created */
1709
+/*********************************************************************//**
1710
+*/
1711
+UNIV_INTERN
1712
+ind_node_t*
1713
+ind_insert_stats_graph_create(
1714
+/*==========================*/
1715
+	dict_index_t*	index,
1716
+	mem_heap_t*	heap);
1717
 /***********************************************************//**
1718
 Creates a table. This is a high-level function used in SQL execution graphs.
1719
 @return	query thread to run next or NULL */
1720
@@ -62,6 +70,13 @@
1721
 /*===================*/
1722
 	que_thr_t*	thr);	/*!< in: query thread */
1723
 /***********************************************************//**
1724
+*/
1725
+UNIV_INTERN
1726
+que_thr_t*
1727
+dict_insert_stats_step(
1728
+/*===================*/
1729
+	que_thr_t*	thr);
1730
+/***********************************************************//**
1731
 Creates an index. This is a high-level function used in SQL execution
1732
 graphs.
1733
 @return	query thread to run next or NULL */
1734
@@ -170,6 +185,7 @@
1735
 	ins_node_t*	field_def; /* child node which does the inserts of
1736
 				the field definitions; the row to be inserted
1737
 				is built by the parent node  */
1738
+	ins_node_t*	stats_def;
1739
 	commit_node_t*	commit_node;
1740
 				/* child node which performs a commit after
1741
 				a successful index creation */
1742
@@ -180,6 +196,7 @@
1743
 	dict_table_t*	table;	/*!< table which owns the index */
1744
 	dtuple_t*	ind_row;/* index definition row built */
1745
 	ulint		field_no;/* next field definition to insert */
1746
+	ulint		stats_no;
1747
 	mem_heap_t*	heap;	/*!< memory heap used as auxiliary storage */
1748
 };
1749
 
1750
@@ -189,6 +206,7 @@
1751
 #define	INDEX_CREATE_INDEX_TREE	3
1752
 #define	INDEX_COMMIT_WORK	4
1753
 #define	INDEX_ADD_TO_CACHE	5
1754
+#define	INDEX_BUILD_STATS_COLS	6
1755
 
1756
 #ifndef UNIV_NONINL
1757
 #include "dict0crea.ic"
148.1.3 by Oleg Tsarev
port patches to 5.5.15
1758
--- a/storage/innobase/include/dict0dict.h
1759
+++ b/storage/innobase/include/dict0dict.h
136.3.2 by Yasufumi Kinoshita
Yasufumi patches are ported to 5.5.14
1760
@@ -1109,10 +1109,18 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1761
 dict_update_statistics(
1762
 /*===================*/
24 by Yasufumi Kinoshita
port Yasufumi's patches to 5.5.8
1763
 	dict_table_t*	table,		/*!< in/out: table */
1764
-	ibool		only_calc_if_missing_stats);/*!< in: only
1765
+	ibool		only_calc_if_missing_stats, /*!< in: only
1766
 					update/recalc the stats if they have
1767
 					not been initialized yet, otherwise
1768
 					do nothing */
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1769
+	ibool		sync);
92.1.1 by Yasufumi Kinoshita
fix bug733317
1770
+/*********************************************************************//**
1771
+*/
1772
+UNIV_INTERN
1773
+ibool
1774
+dict_is_older_statistics(
1775
+/*=====================*/
1776
+	dict_index_t*	index);
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1777
 /********************************************************************//**
1778
 Reserves the dictionary system mutex for MySQL. */
1779
 UNIV_INTERN
136.3.2 by Yasufumi Kinoshita
Yasufumi patches are ported to 5.5.14
1780
@@ -1227,6 +1235,7 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1781
 	dict_table_t*	sys_columns;	/*!< SYS_COLUMNS table */
1782
 	dict_table_t*	sys_indexes;	/*!< SYS_INDEXES table */
1783
 	dict_table_t*	sys_fields;	/*!< SYS_FIELDS table */
1784
+	dict_table_t*	sys_stats;	/*!< SYS_STATS table */
1785
 };
1786
 #endif /* !UNIV_HOTBACKUP */
1787
 
148.1.3 by Oleg Tsarev
port patches to 5.5.15
1788
--- a/storage/innobase/include/dict0load.h
1789
+++ b/storage/innobase/include/dict0load.h
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1790
@@ -41,6 +41,7 @@
1791
 	SYS_FIELDS,
1792
 	SYS_FOREIGN,
1793
 	SYS_FOREIGN_COLS,
1794
+	SYS_STATS,
1795
 
1796
 	/* This must be last item. Defines the number of system tables. */
1797
 	SYS_NUM_SYSTEM_TABLES
136.3.2 by Yasufumi Kinoshita
Yasufumi patches are ported to 5.5.14
1798
@@ -327,6 +328,20 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1799
 	const char**	ref_col_name,	/*!< out: referenced column name
1800
 					in referenced table */
1801
 	ulint*		pos);		/*!< out: column position */
1802
+/********************************************************************//**
1803
+This function parses a SYS_STATS record and extract necessary
1804
+information from the record and return to caller.
1805
+@return error message, or NULL on success */
1806
+UNIV_INTERN
1807
+const char*
1808
+dict_process_sys_stats_rec(
1809
+/*=============================*/
1810
+	mem_heap_t*	heap,		/*!< in/out: heap memory */
1811
+	const rec_t*	rec,		/*!< in: current SYS_STATS rec */
1812
+	index_id_t*	index_id,	/*!< out: INDEX_ID */
1813
+	ulint*		key_cols,	/*!< out: KEY_COLS */
92.1.1 by Yasufumi Kinoshita
fix bug733317
1814
+	ib_uint64_t*	diff_vals,	/*!< out: DIFF_VALS */
1815
+	ib_uint64_t*	non_null_vals);	/*!< out: NON_NULL_VALS */
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1816
 #ifndef UNIV_NONINL
1817
 #include "dict0load.ic"
1818
 #endif
148.1.3 by Oleg Tsarev
port patches to 5.5.15
1819
--- a/storage/innobase/include/que0que.h
1820
+++ b/storage/innobase/include/que0que.h
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1821
@@ -492,6 +492,8 @@
1822
 #define QUE_NODE_CALL		31
1823
 #define QUE_NODE_EXIT		32
1824
 
1825
+#define QUE_NODE_INSERT_STATS	34
1826
+
1827
 /* Query thread states */
1828
 #define QUE_THR_RUNNING		1
1829
 #define QUE_THR_PROCEDURE_WAIT	2
148.1.3 by Oleg Tsarev
port patches to 5.5.15
1830
--- a/storage/innobase/include/row0mysql.h
1831
+++ b/storage/innobase/include/row0mysql.h
92.1.1 by Yasufumi Kinoshita
fix bug733317
1832
@@ -387,6 +387,22 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1833
 					then checked for not being too
1834
 					large. */
1835
 /*********************************************************************//**
1836
+*/
1837
+UNIV_INTERN
1838
+int
1839
+row_insert_stats_for_mysql(
1840
+/*=======================*/
1841
+	dict_index_t*	index,
1842
+	trx_t*		trx);
1843
+/*********************************************************************//**
92.1.1 by Yasufumi Kinoshita
fix bug733317
1844
+*/
1845
+UNIV_INTERN
1846
+int
1847
+row_delete_stats_for_mysql(
1848
+/*=======================*/
1849
+	dict_index_t*	index,
1850
+	trx_t*		trx);
1851
+/*********************************************************************//**
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1852
 Scans a table create SQL string and adds to the data dictionary
1853
 the foreign key constraints declared in the string. This function
1854
 should be called after the indexes for a table have been created.
148.1.3 by Oleg Tsarev
port patches to 5.5.15
1855
--- a/storage/innobase/include/srv0srv.h
1856
+++ b/storage/innobase/include/srv0srv.h
118 by kinoyasu
port Yasufumi patches to 5.5.13
1857
@@ -211,6 +211,9 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1858
 extern ibool	srv_innodb_status;
1859
 
1860
 extern unsigned long long	srv_stats_sample_pages;
1861
+extern ulint	srv_stats_auto_update;
1862
+extern ulint	srv_stats_update_need_lock;
1863
+extern ibool	srv_use_sys_stats_table;
1864
 
1865
 extern ibool	srv_use_doublewrite_buf;
1866
 extern ibool	srv_use_checksums;
148.1.3 by Oleg Tsarev
port patches to 5.5.15
1867
--- a/storage/innobase/que/que0que.c
1868
+++ b/storage/innobase/que/que0que.c
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1869
@@ -621,11 +621,21 @@
1870
 
1871
 		que_graph_free_recursive(cre_ind->ind_def);
1872
 		que_graph_free_recursive(cre_ind->field_def);
1873
+		if (srv_use_sys_stats_table)
1874
+			que_graph_free_recursive(cre_ind->stats_def);
1875
 		que_graph_free_recursive(cre_ind->commit_node);
1876
 
1877
 		mem_heap_free(cre_ind->heap);
1878
 
1879
 		break;
1880
+	case QUE_NODE_INSERT_STATS:
1881
+		cre_ind = node;
1882
+
1883
+		que_graph_free_recursive(cre_ind->stats_def);
1884
+		que_graph_free_recursive(cre_ind->commit_node);
1885
+
1886
+		mem_heap_free(cre_ind->heap);
1887
+		break;
1888
 	case QUE_NODE_PROC:
1889
 		que_graph_free_stat_list(((proc_node_t*)node)->stat_list);
1890
 
1891
@@ -1138,6 +1148,8 @@
1892
 		str = "CREATE TABLE";
1893
 	} else if (type == QUE_NODE_CREATE_INDEX) {
1894
 		str = "CREATE INDEX";
1895
+	} else if (type == QUE_NODE_INSERT_STATS) {
1896
+		str = "INSERT TO SYS_STATS";
1897
 	} else if (type == QUE_NODE_FOR) {
1898
 		str = "FOR LOOP";
1899
 	} else if (type == QUE_NODE_RETURN) {
1900
@@ -1255,6 +1267,8 @@
1901
 		thr = dict_create_table_step(thr);
1902
 	} else if (type == QUE_NODE_CREATE_INDEX) {
1903
 		thr = dict_create_index_step(thr);
1904
+	} else if (type == QUE_NODE_INSERT_STATS) {
1905
+		thr = dict_insert_stats_step(thr);
1906
 	} else if (type == QUE_NODE_ROW_PRINTF) {
1907
 		thr = row_printf_step(thr);
1908
 	} else {
148.1.3 by Oleg Tsarev
port patches to 5.5.15
1909
--- a/storage/innobase/row/row0ins.c
1910
+++ b/storage/innobase/row/row0ins.c
148.1.1 by kinoyasu
Yasufumi patches are ported to 5.5.15
1911
@@ -2013,6 +2013,8 @@
92.1.1 by Yasufumi Kinoshita
fix bug733317
1912
 	}
1913
 
1914
 #ifdef UNIV_DEBUG
1915
+	if (!srv_use_sys_stats_table
1916
+	    || index != UT_LIST_GET_FIRST(dict_sys->sys_stats->indexes))
1917
 	{
1918
 		page_t*	page = btr_cur_get_page(&cursor);
1919
 		rec_t*	first_rec = page_rec_get_next(
148.1.3 by Oleg Tsarev
port patches to 5.5.15
1920
--- a/storage/innobase/row/row0merge.c
1921
+++ b/storage/innobase/row/row0merge.c
118 by kinoyasu
port Yasufumi patches to 5.5.13
1922
@@ -2019,6 +2019,8 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1923
 		"UPDATE SYS_INDEXES SET NAME=CONCAT('"
1924
 		TEMP_INDEX_PREFIX_STR "', NAME) WHERE ID = :indexid;\n"
1925
 		"COMMIT WORK;\n"
1926
+		/* Drop the statistics of the index. */
1927
+		"DELETE FROM SYS_STATS WHERE INDEX_ID = :indexid;\n"
1928
 		/* Drop the field definitions of the index. */
1929
 		"DELETE FROM SYS_FIELDS WHERE INDEX_ID = :indexid;\n"
1930
 		/* Drop the index definition and the B-tree. */
148.1.3 by Oleg Tsarev
port patches to 5.5.15
1931
--- a/storage/innobase/row/row0mysql.c
1932
+++ b/storage/innobase/row/row0mysql.c
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1933
@@ -921,6 +921,9 @@
1934
 
1935
 	table->stat_modified_counter = counter + 1;
1936
 
1937
+	if (!srv_stats_auto_update)
1938
+		return;
1939
+
1940
 	/* Calculate new statistics if 1 / 16 of table has been modified
1941
 	since the last time a statistics batch was run, or if
1942
 	stat_modified_counter > 2 000 000 000 (to avoid wrap-around).
24 by Yasufumi Kinoshita
port Yasufumi's patches to 5.5.8
1943
@@ -931,7 +934,7 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1944
 	    || ((ib_int64_t)counter > 16 + table->stat_n_rows / 16)) {
1945
 
24 by Yasufumi Kinoshita
port Yasufumi's patches to 5.5.8
1946
 		dict_update_statistics(table, FALSE /* update even if stats
1947
-						    are initialized */);
1948
+						    are initialized */, TRUE);
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1949
 	}
1950
 }
1951
 
148.1.1 by kinoyasu
Yasufumi patches are ported to 5.5.15
1952
@@ -2076,6 +2079,71 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1953
 }
1954
 
1955
 /*********************************************************************//**
1956
+*/
1957
+UNIV_INTERN
1958
+int
1959
+row_insert_stats_for_mysql(
1960
+/*=======================*/
1961
+	dict_index_t*	index,
1962
+	trx_t*		trx)
1963
+{
1964
+	ind_node_t*	node;
1965
+	mem_heap_t*	heap;
1966
+	que_thr_t*	thr;
1967
+	ulint		err;
1968
+
118 by kinoyasu
port Yasufumi patches to 5.5.13
1969
+	//ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
1970
+
1971
+	trx->op_info = "try to insert rows to SYS_STATS";
1972
+
1973
+	trx_start_if_not_started(trx);
1974
+	trx->error_state = DB_SUCCESS;
1975
+
1976
+	heap = mem_heap_create(512);
1977
+
1978
+	node = ind_insert_stats_graph_create(index, heap);
1979
+
1980
+	thr = pars_complete_graph_for_exec(node, trx, heap);
1981
+
1982
+	ut_a(thr == que_fork_start_command(que_node_get_parent(thr)));
1983
+	que_run_threads(thr);
1984
+
1985
+	err = trx->error_state;
1986
+
1987
+	que_graph_free((que_t*) que_node_get_parent(thr));
1988
+
1989
+	trx->op_info = "";
1990
+
1991
+	return((int) err);
1992
+}
1993
+
1994
+/*********************************************************************//**
92.1.1 by Yasufumi Kinoshita
fix bug733317
1995
+*/
1996
+UNIV_INTERN
1997
+int
1998
+row_delete_stats_for_mysql(
1999
+/*=============================*/
2000
+	dict_index_t*	index,
2001
+	trx_t*		trx)
2002
+{
2003
+	pars_info_t*	info	= pars_info_create();
2004
+
2005
+	trx->op_info = "delete rows from SYS_STATS";
2006
+
2007
+	trx_start_if_not_started(trx);
2008
+	trx->error_state = DB_SUCCESS;
2009
+
2010
+	pars_info_add_ull_literal(info, "indexid", index->id);
2011
+
2012
+	return((int) que_eval_sql(info,
2013
+				  "PROCEDURE DELETE_STATISTICS_PROC () IS\n"
2014
+				  "BEGIN\n"
2015
+				  "DELETE FROM SYS_STATS WHERE INDEX_ID = :indexid;\n"
2016
+				  "END;\n"
2017
+				  , TRUE, trx));
2018
+}
2019
+
2020
+/*********************************************************************//**
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
2021
 Scans a table create SQL string and adds to the data dictionary
2022
 the foreign key constraints declared in the string. This function
2023
 should be called after the indexes for a table have been created.
148.1.1 by kinoyasu
Yasufumi patches are ported to 5.5.15
2024
@@ -3000,7 +3068,7 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
2025
 	dict_table_autoinc_initialize(table, 1);
2026
 	dict_table_autoinc_unlock(table);
24 by Yasufumi Kinoshita
port Yasufumi's patches to 5.5.8
2027
 	dict_update_statistics(table, FALSE /* update even if stats are
2028
-					    initialized */);
2029
+					    initialized */, TRUE);
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
2030
 
2031
 	trx_commit_for_mysql(trx);
2032
 
148.1.1 by kinoyasu
Yasufumi patches are ported to 5.5.15
2033
@@ -3302,6 +3370,8 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
2034
 			   "       IF (SQL % NOTFOUND) THEN\n"
2035
 			   "               found := 0;\n"
2036
 			   "       ELSE\n"
2037
+			   "               DELETE FROM SYS_STATS\n"
2038
+			   "               WHERE INDEX_ID = index_id;\n"
2039
 			   "               DELETE FROM SYS_FIELDS\n"
2040
 			   "               WHERE INDEX_ID = index_id;\n"
2041
 			   "               DELETE FROM SYS_INDEXES\n"
148.1.3 by Oleg Tsarev
port patches to 5.5.15
2042
--- a/storage/innobase/row/row0row.c
2043
+++ b/storage/innobase/row/row0row.c
148.1.1 by kinoyasu
Yasufumi patches are ported to 5.5.15
2044
@@ -373,6 +373,14 @@
92.1.1 by Yasufumi Kinoshita
fix bug733317
2045
 
2046
 	rec_len = rec_offs_n_fields(offsets);
2047
 
2048
+	if (srv_use_sys_stats_table
2049
+	    && index == UT_LIST_GET_FIRST(dict_sys->sys_stats->indexes)) {
2050
+		if (rec_len < dict_index_get_n_fields(index)) {
2051
+			/* the new record should be extended */
2052
+			rec_len = dict_index_get_n_fields(index);
2053
+		}
2054
+	}
2055
+
2056
 	entry = dtuple_create(heap, rec_len);
2057
 
2058
 	dtuple_set_n_fields_cmp(entry,
148.1.1 by kinoyasu
Yasufumi patches are ported to 5.5.15
2059
@@ -384,6 +392,14 @@
92.1.1 by Yasufumi Kinoshita
fix bug733317
2060
 	for (i = 0; i < rec_len; i++) {
2061
 
2062
 		dfield = dtuple_get_nth_field(entry, i);
2063
+
2064
+		if (srv_use_sys_stats_table
2065
+		    && index == UT_LIST_GET_FIRST(dict_sys->sys_stats->indexes)
2066
+		    && i >= rec_offs_n_fields(offsets)) {
2067
+			dfield_set_null(dfield);
2068
+			continue;
2069
+		}
2070
+
2071
 		field = rec_get_nth_field(rec, offsets, i, &len);
2072
 
2073
 		dfield_set_data(dfield, field, len);
148.1.3 by Oleg Tsarev
port patches to 5.5.15
2074
--- a/storage/innobase/row/row0upd.c
2075
+++ b/storage/innobase/row/row0upd.c
92.1.1 by Yasufumi Kinoshita
fix bug733317
2076
@@ -439,6 +439,12 @@
2077
 				0);
2078
 		}
2079
 
2080
+		if (srv_use_sys_stats_table
2081
+		    && index == UT_LIST_GET_FIRST(dict_sys->sys_stats->indexes)
2082
+		    && upd_field->field_no >= rec_offs_n_fields(offsets)) {
2083
+			return(TRUE);
2084
+		}
2085
+
2086
 		old_len = rec_offs_nth_size(offsets, upd_field->field_no);
2087
 
2088
 		if (rec_offs_comp(offsets)
95 by Yasufumi Kinoshita
Yasufumi patches are ported to 5.5.11; Note: option innodb_extra_rsegments was removed, because the official equivalent option innodb_rollback_segments has been implemented at this version.
2089
@@ -879,6 +885,18 @@
92.1.1 by Yasufumi Kinoshita
fix bug733317
2090
 
2091
 	for (i = 0; i < dtuple_get_n_fields(entry); i++) {
2092
 
2093
+		if (srv_use_sys_stats_table
2094
+		    && index == UT_LIST_GET_FIRST(dict_sys->sys_stats->indexes)
2095
+		    && i >= rec_offs_n_fields(offsets)) {
2096
+			dfield = dtuple_get_nth_field(entry, i);
2097
+
2098
+			upd_field = upd_get_nth_field(update, n_diff);
2099
+			dfield_copy(&(upd_field->new_val), dfield);
2100
+			upd_field_set_field_no(upd_field, i, index, trx);
2101
+			n_diff++;
2102
+			goto skip_compare;
2103
+		}
2104
+
2105
 		data = rec_get_nth_field(rec, offsets, i, &len);
2106
 
2107
 		dfield = dtuple_get_nth_field(entry, i);
148.1.3 by Oleg Tsarev
port patches to 5.5.15
2108
--- a/storage/innobase/srv/srv0srv.c
2109
+++ b/storage/innobase/srv/srv0srv.c
118 by kinoyasu
port Yasufumi patches to 5.5.13
2110
@@ -398,6 +398,9 @@
2 by kinoyasu
ported part of Yasufumi patches until innodb_extend_slow.patch
2111
 /* When estimating number of different key values in an index, sample
2112
 this many index pages */
2113
 UNIV_INTERN unsigned long long	srv_stats_sample_pages = 8;
2114
+UNIV_INTERN ulint	srv_stats_auto_update = 1;
2115
+UNIV_INTERN ulint	srv_stats_update_need_lock = 1;
2116
+UNIV_INTERN ibool	srv_use_sys_stats_table = FALSE;
2117
 
2118
 UNIV_INTERN ibool	srv_use_doublewrite_buf	= TRUE;
2119
 UNIV_INTERN ibool	srv_use_checksums = TRUE;
148.1.3 by Oleg Tsarev
port patches to 5.5.15
2120
--- a/storage/innobase/trx/trx0rec.c
2121
+++ b/storage/innobase/trx/trx0rec.c
136.3.2 by Yasufumi Kinoshita
Yasufumi patches are ported to 5.5.14
2122
@@ -669,15 +669,27 @@
92.1.1 by Yasufumi Kinoshita
fix bug733317
2123
 	/* Save to the undo log the old values of the columns to be updated. */
2124
 
2125
 	if (update) {
2126
+		ulint	extended = 0;
136.3.2 by Yasufumi Kinoshita
Yasufumi patches are ported to 5.5.14
2127
 
92.1.1 by Yasufumi Kinoshita
fix bug733317
2128
 		if (trx_undo_left(undo_page, ptr) < 5) {
2129
 
2130
 			return(0);
2131
 		}
2132
 
2133
-		ptr += mach_write_compressed(ptr, upd_get_n_fields(update));
2134
+		if (srv_use_sys_stats_table
2135
+		    && index == UT_LIST_GET_FIRST(dict_sys->sys_stats->indexes)) {
2136
+			for (i = 0; i < upd_get_n_fields(update); i++) {
2137
+				ulint	pos = upd_get_nth_field(update, i)->field_no;
148.1.3 by Oleg Tsarev
port patches to 5.5.15
2138
 
2139
-		for (i = 0; i < upd_get_n_fields(update); i++) {
92.1.1 by Yasufumi Kinoshita
fix bug733317
2140
+				if (pos >= rec_offs_n_fields(offsets)) {
2141
+					extended++;
2142
+				}
2143
+			}
2144
+		}
2145
+
2146
+		ptr += mach_write_compressed(ptr, upd_get_n_fields(update) - extended);
148.1.3 by Oleg Tsarev
port patches to 5.5.15
2147
+
92.1.1 by Yasufumi Kinoshita
fix bug733317
2148
+		for (i = 0; i < upd_get_n_fields(update) - extended; i++) {
2149
 
2150
 			ulint	pos = upd_get_nth_field(update, i)->field_no;
2151