~percona-dev/percona-server/release-5.1.57-12.8-commit108486

102.1.1 by kinoyasu
add header and rule, as the first step of the reordering patch for separate release
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!
106 by kinoyasu
Port Yasufumi maintaining patches to 5.1.50:
8
diff -ruN a/storage/innodb_plugin/btr/btr0cur.c b/storage/innodb_plugin/btr/btr0cur.c
9
--- a/storage/innodb_plugin/btr/btr0cur.c	2010-08-27 16:13:11.049975230 +0900
10
+++ b/storage/innodb_plugin/btr/btr0cur.c	2010-08-27 16:16:49.201984615 +0900
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
11
@@ -892,6 +892,108 @@
12
 	}
13
 }
14
 
15
+/**********************************************************************//**
16
+Positions a cursor at a randomly chosen position within a B-tree
17
+after the given path
18
+@return TRUE if the position is at the first page, and cursor must point
19
+        the first record for used by the caller.*/
20
+UNIV_INTERN
21
+ibool
22
+btr_cur_open_at_rnd_pos_after_path(
23
+/*====================*/
24
+	dict_index_t*	index,		/*!< in: index */
25
+	ulint		latch_mode,	/*!< in: BTR_SEARCH_LEAF, ... */
26
+	btr_path_t*	first_rec_path,
27
+	btr_cur_t*	cursor,		/*!< in/out: B-tree cursor */
28
+	mtr_t*		mtr)		/*!< in: mtr */
29
+{
30
+	page_cur_t*	page_cursor;
31
+	btr_path_t*	slot;
32
+	ibool		is_first_rec	= TRUE;
33
+	ulint		page_no;
34
+	ulint		space;
35
+	ulint		zip_size;
36
+	ulint		height;
37
+	rec_t*		node_ptr;
38
+	mem_heap_t*	heap		= NULL;
39
+	ulint		offsets_[REC_OFFS_NORMAL_SIZE];
40
+	ulint*		offsets		= offsets_;
41
+	rec_offs_init(offsets_);
42
+
43
+	if (latch_mode == BTR_MODIFY_TREE) {
44
+		mtr_x_lock(dict_index_get_lock(index), mtr);
45
+	} else {
46
+		mtr_s_lock(dict_index_get_lock(index), mtr);
47
+	}
48
+
49
+	page_cursor = btr_cur_get_page_cur(cursor);
50
+	cursor->index = index;
51
+
52
+	space = dict_index_get_space(index);
53
+	zip_size = dict_table_zip_size(index->table);
54
+	page_no = dict_index_get_page(index);
55
+
56
+	height = ULINT_UNDEFINED;
57
+	slot = first_rec_path;
58
+
59
+	for (;;) {
60
+		buf_block_t*	block;
61
+		page_t*		page;
62
+
63
+		block = buf_page_get_gen(space, zip_size, page_no,
64
+					 RW_NO_LATCH, NULL, BUF_GET,
65
+					 __FILE__, __LINE__, mtr);
66
+		page = buf_block_get_frame(block);
67
+		ut_ad(0 == ut_dulint_cmp(index->id,
68
+					 btr_page_get_index_id(page)));
69
+
70
+		if (height == ULINT_UNDEFINED) {
71
+			/* We are in the root node */
72
+
73
+			height = btr_page_get_level(page, mtr);
74
+		}
75
+
76
+		if (height == 0) {
77
+			btr_cur_latch_leaves(page, space, zip_size, page_no,
78
+					     latch_mode, cursor, mtr);
79
+		}
80
+
81
+		if (is_first_rec && slot->nth_rec != ULINT_UNDEFINED) {
82
+			if (height == 0) {
83
+				/* must open the first rec */
84
+				page_cur_open_on_nth_user_rec(block, page_cursor, slot->nth_rec);
85
+			} else {
86
+				is_first_rec = page_cur_open_on_rnd_user_rec_after_nth(block,
87
+								page_cursor, slot->nth_rec);
88
+			}
89
+		} else {
90
+			is_first_rec = FALSE;
91
+			page_cur_open_on_rnd_user_rec(block, page_cursor);
92
+		}
93
+
94
+		if (height == 0) {
95
+			break;
96
+		}
97
+
98
+		ut_ad(height > 0);
99
+
100
+		height--;
101
+		slot++;
102
+
103
+		node_ptr = page_cur_get_rec(page_cursor);
104
+		offsets = rec_get_offsets(node_ptr, cursor->index, offsets,
105
+					  ULINT_UNDEFINED, &heap);
106
+		/* Go to the child node */
107
+		page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
108
+	}
109
+
110
+	if (UNIV_LIKELY_NULL(heap)) {
111
+		mem_heap_free(heap);
112
+	}
113
+
114
+	return (is_first_rec);
115
+}
116
+
117
 /*==================== B-TREE INSERT =========================*/
118
 
119
 /*************************************************************//**
133 by kinoyasu
port maintainer-Yasufumi patches for 5.1.52
120
@@ -3210,6 +3312,154 @@
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
121
 }
122
 
123
 /*******************************************************************//**
124
+Estimates the number of pages which have not null value of the key of n_cols.
125
+@return	estimated number of pages */
126
+UNIV_INTERN
127
+ulint
128
+btr_estimate_n_pages_not_null(
129
+/*=========================*/
130
+	dict_index_t*	index,	/*!< in: index */
131
+	ulint		n_cols,	/*!< in: The cols should be not null */
132
+	btr_path_t*	path1)	/*!< in: path1[BTR_PATH_ARRAY_N_SLOTS] */
133
+{
134
+	dtuple_t*	tuple1;
135
+	btr_path_t	path2[BTR_PATH_ARRAY_N_SLOTS];
136
+	btr_cur_t	cursor;
137
+	btr_path_t*	slot1;
138
+	btr_path_t*	slot2;
139
+	ibool		diverged;
140
+	ibool		diverged_lot;
141
+	ulint		divergence_level;
142
+	ulint		n_pages;
83.2.1 by Oleg Tsarev
fix bug 610525
143
+	ulint		i;
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
144
+	mtr_t		mtr;
145
+	mem_heap_t*	heap;
146
+
147
+	heap = mem_heap_create(n_cols * sizeof(dfield_t)
148
+				+ sizeof(dtuple_t));
149
+
150
+	/* make tuple1 (NULL,NULL,,,) from n_cols */
151
+	tuple1 = dtuple_create(heap, n_cols);
152
+	dict_index_copy_types(tuple1, index, n_cols);
153
+
154
+	for (i = 0; i < n_cols; i++) {
155
+		dfield_set_null(dtuple_get_nth_field(tuple1, i));
156
+	}
157
+
158
+	mtr_start(&mtr);
159
+
160
+	cursor.path_arr = path1;
161
+
162
+	btr_cur_search_to_nth_level(index, 0, tuple1, PAGE_CUR_G,
163
+				    BTR_SEARCH_LEAF | BTR_ESTIMATE,
164
+				    &cursor, 0, __FILE__, __LINE__, &mtr);
165
+
166
+	mtr_commit(&mtr);
167
+
168
+
169
+
170
+	mtr_start(&mtr);
171
+
172
+	cursor.path_arr = path2;
173
+
174
+	btr_cur_open_at_index_side(FALSE, index,
175
+				   BTR_SEARCH_LEAF | BTR_ESTIMATE,
176
+				   &cursor, &mtr);
177
+
178
+	mtr_commit(&mtr);
179
+
180
+	mem_heap_free(heap);
181
+
182
+	/* We have the path information for the range in path1 and path2 */
183
+
184
+	n_pages = 1;
185
+	diverged = FALSE;	    /* This becomes true when the path is not
186
+				    the same any more */
187
+	diverged_lot = FALSE;	    /* This becomes true when the paths are
188
+				    not the same or adjacent any more */
189
+	divergence_level = 1000000; /* This is the level where paths diverged
190
+				    a lot */
191
+	for (i = 0; ; i++) {
192
+		ut_ad(i < BTR_PATH_ARRAY_N_SLOTS);
193
+
194
+		slot1 = path1 + i;
195
+		slot2 = path2 + i;
196
+
197
+		if ((slot1 + 1)->nth_rec == ULINT_UNDEFINED
198
+		    || (slot2 + 1)->nth_rec == ULINT_UNDEFINED) {
199
+
200
+			if (i > divergence_level + 1) {
201
+				/* In trees whose height is > 1 our algorithm
202
+				tends to underestimate: multiply the estimate
203
+				by 2: */
204
+
205
+				n_pages = n_pages * 2;
206
+			}
207
+
208
+			/* Do not estimate the number of rows in the range
209
+			to over 1 / 2 of the estimated rows in the whole
210
+			table */
211
+
212
+			if (n_pages > index->stat_n_leaf_pages / 2) {
213
+				n_pages = index->stat_n_leaf_pages / 2;
214
+
215
+				/* If there are just 0 or 1 rows in the table,
216
+				then we estimate all rows are in the range */
217
+
218
+				if (n_pages == 0) {
219
+					n_pages = index->stat_n_leaf_pages;
220
+				}
221
+			}
222
+
223
+			return(n_pages);
224
+		}
225
+
226
+		if (!diverged && slot1->nth_rec != slot2->nth_rec) {
227
+
228
+			diverged = TRUE;
229
+
230
+			if (slot1->nth_rec < slot2->nth_rec) {
231
+				n_pages = slot2->nth_rec - slot1->nth_rec;
232
+
233
+				if (n_pages > 1) {
234
+					diverged_lot = TRUE;
235
+					divergence_level = i;
236
+				}
237
+			} else {
238
+				/* Maybe the tree has changed between
239
+				searches */
240
+
241
+				return(10);
242
+			}
243
+
244
+		} else if (diverged && !diverged_lot) {
245
+
246
+			if (slot1->nth_rec < slot1->n_recs
247
+			    || slot2->nth_rec > 1) {
248
+
249
+				diverged_lot = TRUE;
250
+				divergence_level = i;
251
+
252
+				n_pages = 0;
253
+
254
+				if (slot1->nth_rec < slot1->n_recs) {
255
+					n_pages += slot1->n_recs
256
+						- slot1->nth_rec;
257
+				}
258
+
259
+				if (slot2->nth_rec > 1) {
260
+					n_pages += slot2->nth_rec - 1;
261
+				}
262
+			}
263
+		} else if (diverged_lot) {
264
+
265
+			n_pages = (n_pages * (slot1->n_recs + slot2->n_recs))
266
+				/ 2;
267
+		}
268
+	}
269
+}
270
+
271
+/*******************************************************************//**
272
 Estimates the number of different key values in a given index, for
273
 each n-column prefix of the index where n <= dict_index_get_n_unique(index).
274
 The estimates are stored in the array index->stat_n_diff_key_vals. */
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
275
@@ -3238,18 +3488,38 @@
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
276
 	ulint		offsets_next_rec_[REC_OFFS_NORMAL_SIZE];
277
 	ulint*		offsets_rec	= offsets_rec_;
278
 	ulint*		offsets_next_rec= offsets_next_rec_;
279
+	ulint		stats_method	= srv_stats_method;
280
+	btr_path_t	first_rec_path[BTR_PATH_ARRAY_N_SLOTS];
281
+	ulint		effective_pages; /* effective leaf pages */
282
 	rec_offs_init(offsets_rec_);
283
 	rec_offs_init(offsets_next_rec_);
284
 
285
 	n_cols = dict_index_get_n_unique(index);
286
 
287
+	if (stats_method == SRV_STATS_METHOD_IGNORE_NULLS) {
288
+		/* estimate effective pages and path for the first effective record */
289
+		/* TODO: make it work also for n_cols > 1. */
290
+		effective_pages = btr_estimate_n_pages_not_null(index, 1 /*k*/, first_rec_path);
291
+
292
+		if (!effective_pages) {
293
+			for (j = 0; j <= n_cols; j++) {
294
+				index->stat_n_diff_key_vals[j] = (ib_int64_t)index->stat_n_leaf_pages;
295
+			}
296
+			return;
297
+		} else if (effective_pages > index->stat_n_leaf_pages) {
298
+			effective_pages = index->stat_n_leaf_pages;
299
+		}
300
+	} else {
301
+		effective_pages = index->stat_n_leaf_pages;
302
+	}
303
+
304
 	n_diff = mem_zalloc((n_cols + 1) * sizeof(ib_int64_t));
305
 
306
 	/* It makes no sense to test more pages than are contained
307
 	in the index, thus we lower the number if it is too high */
308
-	if (srv_stats_sample_pages > index->stat_index_size) {
309
-		if (index->stat_index_size > 0) {
310
-			n_sample_pages = index->stat_index_size;
311
+	if (srv_stats_sample_pages > effective_pages) {
312
+		if (effective_pages > 0) {
313
+			n_sample_pages = effective_pages;
314
 		} else {
315
 			n_sample_pages = 1;
316
 		}
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
317
@@ -3261,9 +3531,15 @@
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
318
 
319
 	for (i = 0; i < n_sample_pages; i++) {
320
 		rec_t*	supremum;
321
+		ibool	is_first_page = TRUE;
322
 		mtr_start(&mtr);
323
 
324
+		if (stats_method == SRV_STATS_METHOD_IGNORE_NULLS) {
325
+			is_first_page = btr_cur_open_at_rnd_pos_after_path(index, BTR_SEARCH_LEAF,
326
+									first_rec_path, &cursor, &mtr);
327
+		} else {
328
 		btr_cur_open_at_rnd_pos(index, BTR_SEARCH_LEAF, &cursor, &mtr);
329
+		}
330
 
331
 		/* Count the number of different key values for each prefix of
332
 		the key on this index page. If the prefix does not determine
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
333
@@ -3274,7 +3550,13 @@
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
334
 		page = btr_cur_get_page(&cursor);
335
 
336
 		supremum = page_get_supremum_rec(page);
337
+		if (stats_method == SRV_STATS_METHOD_IGNORE_NULLS && is_first_page) {
338
+			/* the cursor should be the first record of the page. */
339
+			/* Counting should be started from here. */
340
+			rec = btr_cur_get_rec(&cursor);
341
+		} else {
342
 		rec = page_rec_get_next(page_get_infimum_rec(page));
343
+		}
344
 
345
 		if (rec != supremum) {
346
 			not_empty_flag = 1;
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
347
@@ -3283,7 +3565,8 @@
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
348
 		}
349
 
350
 		while (rec != supremum) {
351
-			rec_t*	next_rec = page_rec_get_next(rec);
352
+			rec_t*  next_rec;
353
+			next_rec = page_rec_get_next(rec);
354
 			if (next_rec == supremum) {
355
 				break;
356
 			}
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
357
@@ -3297,7 +3580,10 @@
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
358
 			cmp_rec_rec_with_match(rec, next_rec,
359
 					       offsets_rec, offsets_next_rec,
360
 					       index, &matched_fields,
361
-					       &matched_bytes);
362
+					       &matched_bytes,
363
+				(stats_method==SRV_STATS_METHOD_NULLS_NOT_EQUAL) ?
364
+				SRV_STATS_METHOD_NULLS_NOT_EQUAL :
365
+				SRV_STATS_METHOD_NULLS_EQUAL);
366
 
367
 			for (j = matched_fields + 1; j <= n_cols; j++) {
368
 				/* We add one if this index record has
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
369
@@ -3358,7 +3644,7 @@
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
370
 	for (j = 0; j <= n_cols; j++) {
371
 		index->stat_n_diff_key_vals[j]
372
 			= ((n_diff[j]
373
-			    * (ib_int64_t)index->stat_n_leaf_pages
374
+			    * (ib_int64_t)effective_pages
375
 			    + n_sample_pages - 1
376
 			    + total_external_size
377
 			    + not_empty_flag)
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
378
@@ -3373,7 +3659,7 @@
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
379
 		different key values, or even more. Let us try to approximate
380
 		that: */
381
 
382
-		add_on = index->stat_n_leaf_pages
383
+		add_on = effective_pages
384
 			/ (10 * (n_sample_pages
385
 				 + total_external_size));
386
 
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
387
@@ -3382,6 +3668,15 @@
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
388
 		}
389
 
390
 		index->stat_n_diff_key_vals[j] += add_on;
391
+
392
+		if (stats_method == SRV_STATS_METHOD_IGNORE_NULLS) {
393
+			/* index->stat_n_diff_key_vals[k] is used for calc rec_per_key,
394
+			as "stats.records / index->stat_n_diff_key_vals[x]".
395
+			So it should be adjusted to the value which is based on whole of the index. */
396
+			index->stat_n_diff_key_vals[j] =
397
+				index->stat_n_diff_key_vals[j] * (ib_int64_t)index->stat_n_leaf_pages
398
+					/ (ib_int64_t)effective_pages;
399
+		}
400
 	}
401
 
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
402
 	mem_free(n_diff);
106 by kinoyasu
Port Yasufumi maintaining patches to 5.1.50:
403
diff -ruN a/storage/innodb_plugin/dict/dict0boot.c b/storage/innodb_plugin/dict/dict0boot.c
404
--- a/storage/innodb_plugin/dict/dict0boot.c	2010-08-27 16:11:12.152990021 +0900
405
+++ b/storage/innodb_plugin/dict/dict0boot.c	2010-08-27 16:16:49.202982244 +0900
65.1.1 by kinoyasu
improve SYS_STATS (for upgreading easily from previous version)
406
@@ -263,6 +263,29 @@
407
 	/* Get the dictionary header */
408
 	dict_hdr = dict_hdr_get(&mtr);
409
 
410
+	if (ut_dulint_cmp(mtr_read_dulint(dict_hdr + DICT_HDR_XTRADB_MARK, &mtr),
411
+			  DICT_HDR_XTRADB_FLAG) != 0) {
412
+		/* not extended yet by XtraDB, need to be extended */
413
+		ulint	root_page_no;
414
+
415
+		root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
416
+					  DICT_HDR_SPACE, 0, DICT_STATS_ID,
417
+					  dict_ind_redundant, &mtr);
418
+		if (root_page_no == FIL_NULL) {
419
+			fprintf(stderr, "InnoDB: Warning: failed to create SYS_STATS btr.\n");
420
+			srv_use_sys_stats_table = FALSE;
421
+		} else {
422
+			mlog_write_ulint(dict_hdr + DICT_HDR_STATS, root_page_no,
423
+					 MLOG_4BYTES, &mtr);
424
+			mlog_write_dulint(dict_hdr + DICT_HDR_XTRADB_MARK,
425
+					  DICT_HDR_XTRADB_FLAG, &mtr);
426
+		}
427
+		mtr_commit(&mtr);
428
+		/* restart mtr */
429
+		mtr_start(&mtr);
78 by kinoyasu
adjust innodb_stats.patch and innodb_overwrite_relay_log_info.patch for UNIV_SYNC_DEBUG
430
+		dict_hdr = dict_hdr_get(&mtr);
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
431
+	}
432
+
65.1.1 by kinoyasu
improve SYS_STATS (for upgreading easily from previous version)
433
 	/* Because we only write new row ids to disk-based data structure
434
 	(dictionary header) when it is divisible by
435
 	DICT_HDR_ROW_ID_WRITE_MARGIN, in recovery we will not recover
436
@@ -424,7 +447,7 @@
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
437
 	table->id = DICT_FIELDS_ID;
438
 	dict_table_add_to_cache(table, heap);
439
 	dict_sys->sys_fields = table;
440
-	mem_heap_free(heap);
441
+	mem_heap_empty(heap);
442
 
443
 	index = dict_mem_index_create("SYS_FIELDS", "CLUST_IND",
444
 				      DICT_HDR_SPACE,
65.1.1 by kinoyasu
improve SYS_STATS (for upgreading easily from previous version)
445
@@ -441,6 +464,41 @@
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
446
 					FALSE);
447
 	ut_a(error == DB_SUCCESS);
448
 
449
+	/*-------------------------*/
450
+	table = dict_mem_table_create("SYS_STATS", DICT_HDR_SPACE, 3, 0);
451
+	table->n_mysql_handles_opened = 1; /* for pin */
452
+
453
+	dict_mem_table_add_col(table, heap, "INDEX_ID", DATA_BINARY, 0, 0);
454
+	dict_mem_table_add_col(table, heap, "KEY_COLS", DATA_INT, 0, 4);
455
+	dict_mem_table_add_col(table, heap, "DIFF_VALS", DATA_BINARY, 0, 0);
456
+
457
+	/* The '+ 2' below comes from the fields DB_TRX_ID, DB_ROLL_PTR */
458
+#if DICT_SYS_STATS_DIFF_VALS_FIELD != 2 + 2
459
+#error "DICT_SYS_STATS_DIFF_VALS_FIELD != 2 + 2"
460
+#endif
461
+
462
+	table->id = DICT_STATS_ID;
463
+	dict_table_add_to_cache(table, heap);
464
+	dict_sys->sys_stats = table;
54.4.3 by kinoyasu
sys_stats: adjust for compatibility, bug fix, information_schema INNODB_SYS_STATS
465
+	mem_heap_empty(heap);
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
466
+
467
+	index = dict_mem_index_create("SYS_STATS", "CLUST_IND",
468
+				      DICT_HDR_SPACE,
469
+				      DICT_UNIQUE | DICT_CLUSTERED, 2);
470
+
471
+	dict_mem_index_add_field(index, "INDEX_ID", 0);
472
+	dict_mem_index_add_field(index, "KEY_COLS", 0);
473
+
474
+	index->id = DICT_STATS_ID;
475
+	error = dict_index_add_to_cache(table, index,
476
+					mtr_read_ulint(dict_hdr
477
+						       + DICT_HDR_STATS,
478
+						       MLOG_4BYTES, &mtr),
479
+					FALSE);
480
+	ut_a(error == DB_SUCCESS);
54.4.3 by kinoyasu
sys_stats: adjust for compatibility, bug fix, information_schema INNODB_SYS_STATS
481
+
482
+	mem_heap_free(heap);
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
483
+
484
 	mtr_commit(&mtr);
485
 	/*-------------------------*/
486
 
65.1.1 by kinoyasu
improve SYS_STATS (for upgreading easily from previous version)
487
@@ -454,6 +512,7 @@
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
488
 	dict_load_sys_table(dict_sys->sys_columns);
489
 	dict_load_sys_table(dict_sys->sys_indexes);
490
 	dict_load_sys_table(dict_sys->sys_fields);
65.1.1 by kinoyasu
improve SYS_STATS (for upgreading easily from previous version)
491
+	dict_load_sys_table(dict_sys->sys_stats);
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
492
 
493
 	mutex_exit(&(dict_sys->mutex));
494
 }
106 by kinoyasu
Port Yasufumi maintaining patches to 5.1.50:
495
diff -ruN a/storage/innodb_plugin/dict/dict0crea.c b/storage/innodb_plugin/dict/dict0crea.c
496
--- a/storage/innodb_plugin/dict/dict0crea.c	2010-08-27 16:11:12.152990021 +0900
497
+++ b/storage/innodb_plugin/dict/dict0crea.c	2010-08-27 16:16:49.205982429 +0900
77 by kinoyasu
port and adjust the part of the patches to 5.1.49: But query_cache_with_comments.patch, response-time-distribution.patch, mysql_remove_eol_carret.patch, log_connection_error.patch, status_wait_query_cache_mutex.patch and sql_no_fcache.patch were not ported yet. Please port them.
498
@@ -508,6 +508,51 @@
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
499
 }
500
 
501
 /*****************************************************************//**
502
+Based on an index object, this function builds the entry to be inserted
503
+in the SYS_STATS system table.
504
+@return	the tuple which should be inserted */
505
+static
506
+dtuple_t*
507
+dict_create_sys_stats_tuple(
508
+/*========================*/
509
+	const dict_index_t*	index,
510
+	ulint			i,
511
+	mem_heap_t*		heap)
512
+{
513
+	dict_table_t*	sys_stats;
514
+	dtuple_t*	entry;
515
+	dfield_t*	dfield;
516
+	byte*		ptr;
517
+
518
+	ut_ad(index);
519
+	ut_ad(heap);
520
+
521
+	sys_stats = dict_sys->sys_stats;
522
+
523
+	entry = dtuple_create(heap, 3 + DATA_N_SYS_COLS);
524
+
525
+	dict_table_copy_types(entry, sys_stats);
526
+
527
+	/* 0: INDEX_ID -----------------------*/
528
+	dfield = dtuple_get_nth_field(entry, 0/*INDEX_ID*/);
529
+	ptr = mem_heap_alloc(heap, 8);
530
+	mach_write_to_8(ptr, index->id);
531
+	dfield_set_data(dfield, ptr, 8);
532
+	/* 1: KEY_COLS -----------------------*/
533
+	dfield = dtuple_get_nth_field(entry, 1/*KEY_COLS*/);
534
+	ptr = mem_heap_alloc(heap, 4);
535
+	mach_write_to_4(ptr, i);
536
+	dfield_set_data(dfield, ptr, 4);
537
+	/* 4: DIFF_VALS ----------------------*/
538
+	dfield = dtuple_get_nth_field(entry, 2/*DIFF_VALS*/);
539
+	ptr = mem_heap_alloc(heap, 8);
540
+	mach_write_to_8(ptr, ut_dulint_zero); /* initial value is 0 */
541
+	dfield_set_data(dfield, ptr, 8);
542
+
543
+	return(entry);
544
+}
545
+
546
+/*****************************************************************//**
547
 Creates the tuple with which the index entry is searched for writing the index
548
 tree root page number, if such a tree is created.
549
 @return	the tuple for search */
77 by kinoyasu
port and adjust the part of the patches to 5.1.49: But query_cache_with_comments.patch, response-time-distribution.patch, mysql_remove_eol_carret.patch, log_connection_error.patch, status_wait_query_cache_mutex.patch and sql_no_fcache.patch were not ported yet. Please port them.
550
@@ -617,6 +662,27 @@
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
551
 }
552
 
553
 /***************************************************************//**
554
+Builds a row for storing stats to insert.
555
+@return DB_SUCCESS */
556
+static
557
+ulint
558
+dict_build_stats_def_step(
559
+/*======================*/
560
+	ind_node_t*	node)
561
+{
562
+	dict_index_t*	index;
563
+	dtuple_t*	row;
564
+
565
+	index = node->index;
566
+
567
+	row = dict_create_sys_stats_tuple(index, node->stats_no, node->heap);
568
+
569
+	ins_node_set_new_row(node->stats_def, row);
570
+
571
+	return(DB_SUCCESS);
572
+}
573
+
574
+/***************************************************************//**
575
 Creates an index tree for the index if it is not a member of a cluster.
576
 @return	DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
577
 static
133 by kinoyasu
port maintainer-Yasufumi patches for 5.1.52
578
@@ -938,6 +1004,49 @@
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
579
 					  dict_sys->sys_fields, heap);
580
 	node->field_def->common.parent = node;
581
 
54.4.3 by kinoyasu
sys_stats: adjust for compatibility, bug fix, information_schema INNODB_SYS_STATS
582
+	if (srv_use_sys_stats_table) {
583
+		node->stats_def = ins_node_create(INS_DIRECT,
584
+						  dict_sys->sys_stats, heap);
585
+		node->stats_def->common.parent = node;
586
+	} else {
587
+		node->stats_def = NULL;
588
+	}
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
589
+
65.1.1 by kinoyasu
improve SYS_STATS (for upgreading easily from previous version)
590
+	node->commit_node = commit_node_create(heap);
591
+	node->commit_node->common.parent = node;
592
+
593
+	return(node);
594
+}
595
+
596
+/*********************************************************************//**
597
+*/
598
+UNIV_INTERN
599
+ind_node_t*
600
+ind_insert_stats_graph_create(
601
+/*==========================*/
602
+	dict_index_t*	index,
603
+	mem_heap_t*	heap)
604
+{
605
+	ind_node_t*	node;
606
+
607
+	node = mem_heap_alloc(heap, sizeof(ind_node_t));
608
+
609
+	node->common.type = QUE_NODE_INSERT_STATS;
610
+
611
+	node->index = index;
612
+
613
+	node->state = INDEX_BUILD_STATS_COLS;
614
+	node->page_no = FIL_NULL;
615
+	node->heap = mem_heap_create(256);
616
+
617
+	node->ind_def = NULL;
618
+	node->field_def = NULL;
619
+
620
+	node->stats_def = ins_node_create(INS_DIRECT,
621
+					  dict_sys->sys_stats, heap);
622
+	node->stats_def->common.parent = node;
623
+	node->stats_no = 0;
624
+
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
625
 	node->commit_node = commit_node_create(heap);
626
 	node->commit_node->common.parent = node;
627
 
133 by kinoyasu
port maintainer-Yasufumi patches for 5.1.52
628
@@ -1088,6 +1197,7 @@
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
629
 
630
 		node->state = INDEX_BUILD_FIELD_DEF;
631
 		node->field_no = 0;
632
+		node->stats_no = 0;
633
 
634
 		thr->run_node = node->ind_def;
635
 
133 by kinoyasu
port maintainer-Yasufumi patches for 5.1.52
636
@@ -1133,7 +1243,31 @@
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
637
 			goto function_exit;
638
 		}
639
 
640
-		node->state = INDEX_CREATE_INDEX_TREE;
106.1.1 by kinoyasu
sys_stats table is used only for not-temporary tables
641
+		if (srv_use_sys_stats_table
642
+		    && !((node->table->flags >> DICT_TF2_SHIFT) & DICT_TF2_TEMPORARY)) {
54.4.3 by kinoyasu
sys_stats: adjust for compatibility, bug fix, information_schema INNODB_SYS_STATS
643
+			node->state = INDEX_BUILD_STATS_COLS;
644
+		} else {
645
+			node->state = INDEX_CREATE_INDEX_TREE;
646
+		}
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
647
+	}
648
+	if (node->state == INDEX_BUILD_STATS_COLS) {
649
+		if (node->stats_no <= dict_index_get_n_unique(node->index)) {
650
+
651
+			err = dict_build_stats_def_step(node);
652
+
653
+			if (err != DB_SUCCESS) {
654
+
655
+				goto function_exit;
656
+			}
657
+
658
+			node->stats_no++;
659
+
660
+			thr->run_node = node->stats_def;
661
+
662
+			return(thr);
663
+		} else {
664
+			node->state = INDEX_CREATE_INDEX_TREE;
665
+		}
666
 	}
667
 
668
 	if (node->state == INDEX_CREATE_INDEX_TREE) {
133 by kinoyasu
port maintainer-Yasufumi patches for 5.1.52
669
@@ -1179,6 +1313,66 @@
106 by kinoyasu
Port Yasufumi maintaining patches to 5.1.50:
670
 		return(NULL);
671
 	}
65.1.1 by kinoyasu
improve SYS_STATS (for upgreading easily from previous version)
672
 
106 by kinoyasu
Port Yasufumi maintaining patches to 5.1.50:
673
+	thr->run_node = que_node_get_parent(node);
674
+
675
+	return(thr);
676
+}
677
+
678
+/****************************************************************//**
65.1.1 by kinoyasu
improve SYS_STATS (for upgreading easily from previous version)
679
+*/
680
+UNIV_INTERN
681
+que_thr_t*
682
+dict_insert_stats_step(
683
+/*===================*/
684
+	que_thr_t*	thr)	/*!< in: query thread */
685
+{
686
+	ind_node_t*	node;
687
+	ulint		err	= DB_ERROR;
688
+	trx_t*		trx;
689
+
690
+	ut_ad(thr);
691
+
692
+	trx = thr_get_trx(thr);
693
+
694
+	node = thr->run_node;
695
+
696
+	if (thr->prev_node == que_node_get_parent(node)) {
697
+		node->state = INDEX_BUILD_STATS_COLS;
698
+	}
699
+
700
+	if (node->state == INDEX_BUILD_STATS_COLS) {
701
+		if (node->stats_no <= dict_index_get_n_unique(node->index)) {
702
+
703
+			err = dict_build_stats_def_step(node);
704
+
705
+			if (err != DB_SUCCESS) {
706
+
707
+				goto function_exit;
708
+			}
709
+
710
+			node->stats_no++;
711
+
712
+			thr->run_node = node->stats_def;
713
+
714
+			return(thr);
715
+		} else {
716
+			node->state = INDEX_COMMIT_WORK;
717
+		}
718
+	}
719
+
720
+	if (node->state == INDEX_COMMIT_WORK) {
721
+
722
+		/* do not commit transaction here for now */
723
+	}
724
+
725
+function_exit:
726
+	trx->error_state = err;
727
+
728
+	if (err == DB_SUCCESS) {
729
+	} else {
730
+		return(NULL);
731
+	}
732
+
106 by kinoyasu
Port Yasufumi maintaining patches to 5.1.50:
733
 	thr->run_node = que_node_get_parent(node);
734
 
735
 	return(thr);
736
diff -ruN a/storage/innodb_plugin/dict/dict0dict.c b/storage/innodb_plugin/dict/dict0dict.c
737
--- a/storage/innodb_plugin/dict/dict0dict.c	2010-08-27 16:11:12.155144214 +0900
738
+++ b/storage/innodb_plugin/dict/dict0dict.c	2010-08-27 16:16:49.213982476 +0900
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
739
@@ -739,7 +739,7 @@
740
 		print an error message and return without doing
741
 		anything. */
742
 		dict_update_statistics(table, TRUE /* only update stats
743
-				       if they have not been initialized */);
744
+				       if they have not been initialized */, FALSE);
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
745
 	}
746
 
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
747
 	return(table);
748
@@ -4276,6 +4276,255 @@
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
749
 }
750
 
751
 /*********************************************************************//**
752
+functions to use SYS_STATS system table. */
753
+static
754
+ibool
755
+dict_reload_statistics(
756
+/*===================*/
757
+	dict_table_t*	table,
758
+	ulint*		sum_of_index_sizes)
759
+{
760
+	dict_index_t*	index;
761
+	ulint		size;
762
+	mem_heap_t*	heap;
763
+
764
+	index = dict_table_get_first_index(table);
765
+
766
+	if (index == NULL) {
767
+		/* Table definition is corrupt */
768
+
769
+		return(FALSE);
770
+	}
771
+
772
+	heap = mem_heap_create(1000);
773
+
774
+	while (index) {
775
+		if (table->is_corrupt) {
776
+			ut_a(srv_pass_corrupt_table);
777
+			mem_heap_free(heap);
778
+			return(FALSE);
779
+		}
780
+
781
+		size = btr_get_size(index, BTR_TOTAL_SIZE);
782
+
783
+		index->stat_index_size = size;
784
+
785
+		*sum_of_index_sizes += size;
786
+
787
+		size = btr_get_size(index, BTR_N_LEAF_PAGES);
788
+
789
+		if (size == 0) {
790
+			/* The root node of the tree is a leaf */
791
+			size = 1;
792
+		}
793
+
794
+		index->stat_n_leaf_pages = size;
795
+
796
+/*===========================================*/
797
+{
798
+	dict_table_t*	sys_stats;
799
+	dict_index_t*	sys_index;
800
+	btr_pcur_t	pcur;
801
+	dtuple_t*	tuple;
802
+	dfield_t*	dfield;
803
+	ulint		key_cols;
804
+	ulint		n_cols;
805
+	const rec_t*	rec;
806
+	const byte*	field;
807
+	ulint		len;
808
+	ib_int64_t*	stat_n_diff_key_vals_tmp;
809
+	byte*		buf;
810
+	ulint		i;
811
+	mtr_t		mtr;
812
+
813
+	n_cols = dict_index_get_n_unique(index);
814
+	stat_n_diff_key_vals_tmp = mem_heap_zalloc(heap, (n_cols + 1) * sizeof(ib_int64_t));
815
+
816
+	sys_stats = dict_sys->sys_stats;
817
+	sys_index = UT_LIST_GET_FIRST(sys_stats->indexes);
818
+	ut_a(!dict_table_is_comp(sys_stats));
819
+
820
+	tuple = dtuple_create(heap, 1);
821
+	dfield = dtuple_get_nth_field(tuple, 0);
822
+
823
+	buf = mem_heap_alloc(heap, 8);
824
+	mach_write_to_8(buf, index->id);
825
+
826
+	dfield_set_data(dfield, buf, 8);
827
+	dict_index_copy_types(tuple, sys_index, 1);
828
+
829
+	mtr_start(&mtr);
830
+
831
+	btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
832
+				  BTR_SEARCH_LEAF, &pcur, &mtr);
833
+	for (i = 0; i <= n_cols; i++) {
834
+		rec = btr_pcur_get_rec(&pcur);
835
+
54.4.3 by kinoyasu
sys_stats: adjust for compatibility, bug fix, information_schema INNODB_SYS_STATS
836
+		if (!btr_pcur_is_on_user_rec(&pcur)
837
+		    || ut_dulint_cmp(mach_read_from_8(rec_get_nth_field_old(rec, 0, &len)),
838
+				     index->id)) {
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
839
+			/* not found: even 1 if not found should not be alowed */
840
+			fprintf(stderr, "InnoDB: Warning: stats for %s/%s (%lu/%lu)"
841
+				        " not fonund in SYS_STATS\n",
842
+					index->table_name, index->name, i, n_cols);
843
+			btr_pcur_close(&pcur);
844
+			mtr_commit(&mtr);
845
+			mem_heap_free(heap);
846
+			return(FALSE);
847
+		}
848
+
849
+		if (rec_get_deleted_flag(rec, 0)) {
850
+			goto next_rec;
851
+		}
852
+
853
+		field = rec_get_nth_field_old(rec, 1, &len);
854
+		ut_a(len == 4);
855
+
856
+		key_cols = mach_read_from_4(field);
857
+
858
+		ut_a(i == key_cols);
859
+
860
+		field = rec_get_nth_field_old(rec, DICT_SYS_STATS_DIFF_VALS_FIELD, &len);
861
+		ut_a(len == 8);
862
+
863
+		stat_n_diff_key_vals_tmp[i] = ut_conv_dulint_to_longlong(mach_read_from_8(field));
864
+next_rec:
865
+		btr_pcur_move_to_next_user_rec(&pcur, &mtr);
866
+	}
867
+
868
+	btr_pcur_close(&pcur);
869
+	mtr_commit(&mtr);
870
+
871
+	for (i = 0; i <= n_cols; i++) {
872
+		index->stat_n_diff_key_vals[i] = stat_n_diff_key_vals_tmp[i];
873
+	}
874
+}
875
+/*===========================================*/
876
+
877
+		index = dict_table_get_next_index(index);
878
+	}
879
+
880
+	mem_heap_free(heap);
881
+	return(TRUE);
882
+}
883
+
884
+static
885
+void
886
+dict_store_statistics(
887
+/*==================*/
888
+	dict_table_t*	table)
889
+{
890
+	dict_index_t*	index;
891
+	mem_heap_t*	heap;
892
+
893
+	index = dict_table_get_first_index(table);
894
+
895
+	ut_a(index);
896
+
897
+	heap = mem_heap_create(1000);
898
+
899
+	while (index) {
900
+		if (table->is_corrupt) {
901
+			ut_a(srv_pass_corrupt_table);
902
+			mem_heap_free(heap);
903
+			return;
904
+		}
905
+
906
+/*===========================================*/
907
+{
908
+	dict_table_t*	sys_stats;
909
+	dict_index_t*	sys_index;
910
+	btr_pcur_t	pcur;
911
+	dtuple_t*	tuple;
912
+	dfield_t*	dfield;
913
+	ulint		key_cols;
914
+	ulint		n_cols;
915
+	ulint		rests;
916
+	const rec_t*	rec;
917
+	const byte*	field;
918
+	ulint		len;
919
+	ib_int64_t*	stat_n_diff_key_vals_tmp;
920
+	byte*		buf;
921
+	ulint		i;
922
+	mtr_t		mtr;
923
+
924
+	n_cols = dict_index_get_n_unique(index);
925
+	stat_n_diff_key_vals_tmp = mem_heap_zalloc(heap, (n_cols + 1) * sizeof(ib_int64_t));
926
+
927
+	for (i = 0; i <= n_cols; i++) {
928
+		stat_n_diff_key_vals_tmp[i] = index->stat_n_diff_key_vals[i];
929
+	}
930
+
931
+	sys_stats = dict_sys->sys_stats;
932
+	sys_index = UT_LIST_GET_FIRST(sys_stats->indexes);
933
+	ut_a(!dict_table_is_comp(sys_stats));
934
+
935
+	tuple = dtuple_create(heap, 1);
936
+	dfield = dtuple_get_nth_field(tuple, 0);
937
+
938
+	buf = mem_heap_alloc(heap, 8);
939
+	mach_write_to_8(buf, index->id);
940
+
941
+	dfield_set_data(dfield, buf, 8);
942
+	dict_index_copy_types(tuple, sys_index, 1);
943
+
944
+	mtr_start(&mtr);
945
+
946
+	btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
947
+				  BTR_MODIFY_LEAF, &pcur, &mtr);
948
+	rests = n_cols + 1;
949
+	for (i = 0; i <= n_cols; i++) {
950
+		rec = btr_pcur_get_rec(&pcur);
951
+
54.4.3 by kinoyasu
sys_stats: adjust for compatibility, bug fix, information_schema INNODB_SYS_STATS
952
+		if (!btr_pcur_is_on_user_rec(&pcur)
953
+		    || ut_dulint_cmp(mach_read_from_8(rec_get_nth_field_old(rec, 0, &len)),
954
+				     index->id)) {
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
955
+			/* not found */
956
+			btr_pcur_close(&pcur);
957
+			mtr_commit(&mtr);
958
+			break;
959
+		}
960
+
961
+		if (rec_get_deleted_flag(rec, 0)) {
962
+			goto next_rec;
963
+		}
964
+
965
+		field = rec_get_nth_field_old(rec, 1, &len);
966
+		ut_a(len == 4);
967
+
968
+		key_cols = mach_read_from_4(field);
969
+
970
+		field = rec_get_nth_field_old(rec, DICT_SYS_STATS_DIFF_VALS_FIELD, &len);
971
+		ut_a(len == 8);
972
+
973
+		mlog_write_dulint((byte*)field,
974
+				ut_dulint_create((ulint) (stat_n_diff_key_vals_tmp[key_cols] >> 32),
975
+						(ulint) stat_n_diff_key_vals_tmp[key_cols] & 0xFFFFFFFF),
976
+				&mtr);
977
+
978
+		rests--;
979
+
980
+next_rec:
981
+		btr_pcur_move_to_next_user_rec(&pcur, &mtr);
982
+	}
983
+	btr_pcur_close(&pcur);
984
+	mtr_commit(&mtr);
985
+
986
+	if (rests) {
987
+		fprintf(stderr, "InnoDB: Warning: failed to store %lu stats entries"
988
+				" of %s/%s to SYS_STATS system table.\n",
989
+				rests, index->table_name, index->name);
990
+	}
991
+}
992
+/*===========================================*/
993
+
994
+		index = dict_table_get_next_index(index);
995
+	}
996
+
997
+	mem_heap_free(heap);
998
+}
999
+
1000
+/*********************************************************************//**
1001
 Calculates new estimates for table and index statistics. The statistics
1002
 are used in query optimization. */
1003
 UNIV_INTERN
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
1004
@@ -4283,10 +4532,11 @@
1005
 dict_update_statistics(
1006
 /*===================*/
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
1007
 	dict_table_t*	table,		/*!< in/out: table */
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
1008
-	ibool		only_calc_if_missing_stats)/*!< in: only
1009
+	ibool		only_calc_if_missing_stats,	/*!< in: only
1010
 					update/recalc the stats if they have
1011
 					not been initialized yet, otherwise
1012
 					do nothing */
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
1013
+	ibool		sync)		/*!< in: TRUE if must update SYS_STATS */
1014
 {
1015
 	dict_index_t*	index;
127 by kinoyasu
port maintainer-Yasufumi patches for 5.1.51
1016
 	ulint		sum_of_index_sizes	= 0;
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
1017
@@ -4303,6 +4553,27 @@
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
1018
 		return;
1019
 	}
1020
 
106.1.1 by kinoyasu
sys_stats table is used only for not-temporary tables
1021
+	if (srv_use_sys_stats_table && !((table->flags >> DICT_TF2_SHIFT) & DICT_TF2_TEMPORARY) && !sync) {
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
1022
+		dict_table_stats_lock(table, RW_X_LATCH);
1023
+
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
1024
+		/* reload statistics from SYS_STATS table */
1025
+		if (dict_reload_statistics(table, &sum_of_index_sizes)) {
1026
+			/* success */
1027
+#ifdef UNIV_DEBUG
1028
+			fprintf(stderr, "InnoDB: DEBUG: reload_statistics is scceeded for %s.\n",
1029
+					table->name);
1030
+#endif
1031
+			goto end;
1032
+		}
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
1033
+
1034
+		dict_table_stats_unlock(table, RW_X_LATCH);
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
1035
+	}
1036
+#ifdef UNIV_DEBUG
1037
+	fprintf(stderr, "InnoDB: DEBUG: update_statistics for %s.\n",
1038
+			table->name);
1039
+#endif
1040
+	sum_of_index_sizes = 0;
1041
+
1042
 	/* Find out the sizes of the indexes and how many different values
1043
 	for the key they approximately have */
1044
 
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
1045
@@ -4363,6 +4634,11 @@
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
1046
 		index = dict_table_get_next_index(index);
127 by kinoyasu
port maintainer-Yasufumi patches for 5.1.51
1047
 	} while (index);
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
1048
 
106.1.1 by kinoyasu
sys_stats table is used only for not-temporary tables
1049
+	if (srv_use_sys_stats_table && !((table->flags >> DICT_TF2_SHIFT) & DICT_TF2_TEMPORARY)) {
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
1050
+		/* store statistics to SYS_STATS table */
1051
+		dict_store_statistics(table);
1052
+	}
1053
+end:
1054
 	index = dict_table_get_first_index(table);
1055
 
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
1056
 	table->stat_n_rows = index->stat_n_diff_key_vals[
1057
@@ -4457,7 +4733,7 @@
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
1058
 
1059
 	ut_ad(mutex_own(&(dict_sys->mutex)));
1060
 
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
1061
-	dict_update_statistics(table, FALSE /* update even if initialized */);
1062
+	dict_update_statistics(table, FALSE /* update even if initialized */, FALSE);
1063
 
1064
 	dict_table_stats_lock(table, RW_S_LATCH);
1065
 
106 by kinoyasu
Port Yasufumi maintaining patches to 5.1.50:
1066
diff -ruN a/storage/innodb_plugin/dict/dict0load.c b/storage/innodb_plugin/dict/dict0load.c
1067
--- a/storage/innodb_plugin/dict/dict0load.c	2010-08-04 02:24:19.000000000 +0900
1068
+++ b/storage/innodb_plugin/dict/dict0load.c	2010-08-27 16:16:49.218982387 +0900
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
1069
@@ -223,7 +223,7 @@
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
1070
 
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
1071
 			if (dict_table_get_first_index(table)) {
1072
 				dict_update_statistics(table, FALSE /* update
1073
-						       even if initialized */);
1074
+						       even if initialized */, FALSE);
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
1075
 			}
1076
 
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
1077
 			dict_table_print_low(table);
106 by kinoyasu
Port Yasufumi maintaining patches to 5.1.50:
1078
diff -ruN a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc
1079
--- a/storage/innodb_plugin/handler/ha_innodb.cc	2010-08-27 16:15:55.192417748 +0900
1080
+++ b/storage/innodb_plugin/handler/ha_innodb.cc	2010-08-27 16:16:49.233984845 +0900
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
1081
@@ -190,6 +190,7 @@
1082
 static my_bool	innobase_rollback_on_timeout		= FALSE;
1083
 static my_bool	innobase_create_status_file		= FALSE;
1084
 static my_bool	innobase_stats_on_metadata		= TRUE;
1085
+static my_bool	innobase_use_sys_stats_table		= FALSE;
1086
 
1087
 static char*	internal_innobase_data_file_path	= NULL;
1088
 
127 by kinoyasu
port maintainer-Yasufumi patches for 5.1.51
1089
@@ -2211,6 +2212,8 @@
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
1090
 
1091
 	srv_extra_undoslots = (ibool) innobase_extra_undoslots;
1092
 
1093
+	srv_use_sys_stats_table = (ibool) innobase_use_sys_stats_table;
1094
+
1095
 	/* -------------- Log files ---------------------------*/
1096
 
1097
 	/* The default dir for log files is the datadir of MySQL */
149 by kinoyasu
ported Yasufumi patches for 5.1.53
1098
@@ -4981,6 +4984,10 @@
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
1099
 
1100
 	error = row_insert_for_mysql((byte*) record, prebuilt);
1101
 
1102
+#ifdef EXTENDED_FOR_USERSTAT
1103
+	if (error == DB_SUCCESS) rows_changed++;
1104
+#endif
1105
+
1106
 	/* Handle duplicate key errors */
1107
 	if (auto_inc_used) {
1108
 		ulint		err;
149 by kinoyasu
ported Yasufumi patches for 5.1.53
1109
@@ -5317,6 +5324,10 @@
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
1110
 		}
1111
 	}
1112
 
1113
+#ifdef EXTENDED_FOR_USERSTAT
1114
+	if (error == DB_SUCCESS) rows_changed++;
1115
+#endif
1116
+
1117
 	innodb_srv_conc_exit_innodb(trx);
1118
 
1119
 	error = convert_error_code_to_mysql(error,
149 by kinoyasu
ported Yasufumi patches for 5.1.53
1120
@@ -5370,6 +5381,10 @@
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
1121
 
1122
 	error = row_update_for_mysql((byte*) record, prebuilt);
1123
 
1124
+#ifdef EXTENDED_FOR_USERSTAT
1125
+	if (error == DB_SUCCESS) rows_changed++;
1126
+#endif
1127
+
1128
 	innodb_srv_conc_exit_innodb(trx);
1129
 
1130
 	error = convert_error_code_to_mysql(
149 by kinoyasu
ported Yasufumi patches for 5.1.53
1131
@@ -5897,6 +5912,11 @@
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
1132
 	case DB_SUCCESS:
1133
 		error = 0;
1134
 		table->status = 0;
1135
+#ifdef EXTENDED_FOR_USERSTAT
1136
+		rows_read++;
1137
+		if (active_index >= 0 && active_index < MAX_KEY)
1138
+			index_rows_read[active_index]++;
1139
+#endif
1140
 		break;
1141
 	case DB_RECORD_NOT_FOUND:
1142
 		error = HA_ERR_END_OF_FILE;
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
1143
@@ -7783,11 +7803,31 @@
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
1144
 			/* In sql_show we call with this flag: update
1145
 			then statistics so that they are up-to-date */
1146
 
106.1.1 by kinoyasu
sys_stats table is used only for not-temporary tables
1147
+			if (srv_use_sys_stats_table && !((ib_table->flags >> DICT_TF2_SHIFT) & DICT_TF2_TEMPORARY)
149 by kinoyasu
ported Yasufumi patches for 5.1.53
1148
+			    && called_from_analyze) {
65.1.1 by kinoyasu
improve SYS_STATS (for upgreading easily from previous version)
1149
+				/* If the indexes on the table don't have enough rows in SYS_STATS system table, */
1150
+				/* they need to be created. */
1151
+				dict_index_t*	index;
1152
+
1153
+				prebuilt->trx->op_info = "confirming rows of SYS_STATS to store statistics";
1154
+
1155
+				ut_a(prebuilt->trx->conc_state == TRX_NOT_STARTED);
1156
+
1157
+				for (index = dict_table_get_first_index(ib_table);
1158
+				     index != NULL;
1159
+				     index = dict_table_get_next_index(index)) {
1160
+					row_insert_stats_for_mysql(index, prebuilt->trx);
1161
+					innobase_commit_low(prebuilt->trx);
1162
+				}
1163
+
1164
+				ut_a(prebuilt->trx->conc_state == TRX_NOT_STARTED);
1165
+			}
1166
+
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
1167
 			prebuilt->trx->op_info = "updating table statistics";
1168
 
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
1169
 			dict_update_statistics(ib_table,
1170
 					       FALSE /* update even if stats
1171
-						     are initialized */);
1172
+						     are initialized */, called_from_analyze);
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
1173
 
1174
 			prebuilt->trx->op_info = "returning various info to MySQL";
1175
 		}
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
1176
@@ -7865,7 +7905,7 @@
127 by kinoyasu
port maintainer-Yasufumi patches for 5.1.51
1177
 		are asked by MySQL to avoid locking. Another reason to
1178
 		avoid the call is that it uses quite a lot of CPU.
1179
 		See Bug#38185. */
1180
-		if (flag & HA_STATUS_NO_LOCK) {
1181
+		if (flag & HA_STATUS_NO_LOCK || !srv_stats_update_need_lock) {
1182
 			/* We do not update delete_length if no
1183
 			locking is requested so the "old" value can
1184
 			remain. delete_length is initialized to 0 in
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
1185
@@ -11045,6 +11085,45 @@
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
1186
   "The number of index pages to sample when calculating statistics (default 8)",
1187
   NULL, NULL, 8, 1, ~0ULL, 0);
1188
 
1189
+const char *innobase_stats_method_names[]=
1190
+{
1191
+  "nulls_equal",
1192
+  "nulls_unequal",
1193
+  "nulls_ignored",
1194
+  NullS
1195
+};
1196
+TYPELIB innobase_stats_method_typelib=
1197
+{
1198
+  array_elements(innobase_stats_method_names) - 1, "innobase_stats_method_typelib",
1199
+  innobase_stats_method_names, NULL
1200
+};
1201
+static MYSQL_SYSVAR_ENUM(stats_method, srv_stats_method,
1202
+  PLUGIN_VAR_RQCMDARG,
1203
+  "Specifies how InnoDB index statistics collection code should threat NULLs. "
1204
+  "Possible values of name are same to for 'myisam_stats_method'. "
1205
+  "This is startup parameter.",
1206
+  NULL, NULL, 0, &innobase_stats_method_typelib);
1207
+
1208
+static MYSQL_SYSVAR_ULONG(stats_auto_update, srv_stats_auto_update,
1209
+  PLUGIN_VAR_RQCMDARG,
1210
+  "Enable/Disable InnoDB's auto update statistics of indexes. "
1211
+  "(except for ANALYZE TABLE command) 0:disable 1:enable",
1212
+  NULL, NULL, 1, 0, 1, 0);
1213
+
1214
+static MYSQL_SYSVAR_ULONG(stats_update_need_lock, srv_stats_update_need_lock,
1215
+  PLUGIN_VAR_RQCMDARG,
1216
+  "Enable/Disable InnoDB's update statistics which needs to lock dictionary. "
1217
+  "e.g. Data_free.",
1218
+  NULL, NULL, 1, 0, 1, 0);
1219
+
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
1220
+static MYSQL_SYSVAR_BOOL(use_sys_stats_table, innobase_use_sys_stats_table,
1221
+  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
1222
+  "Enable to use SYS_STATS system table to store statistics statically, "
1223
+  "And avoids to calculate statistics at every first open of the tables. "
1224
+  "This option may make the opportunities of update statistics less. "
1225
+  "So you should use ANALYZE TABLE command intentionally.",
1226
+  NULL, NULL, FALSE);
1227
+
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
1228
 static MYSQL_SYSVAR_BOOL(adaptive_hash_index, btr_search_enabled,
1229
   PLUGIN_VAR_OPCMDARG,
1230
   "Enable InnoDB adaptive hash index (enabled by default).  "
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
1231
@@ -11363,6 +11442,10 @@
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
1232
   MYSQL_SYSVAR(overwrite_relay_log_info),
1233
   MYSQL_SYSVAR(rollback_on_timeout),
1234
   MYSQL_SYSVAR(stats_on_metadata),
1235
+  MYSQL_SYSVAR(stats_method),
1236
+  MYSQL_SYSVAR(stats_auto_update),
1237
+  MYSQL_SYSVAR(stats_update_need_lock),
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
1238
+  MYSQL_SYSVAR(use_sys_stats_table),
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
1239
   MYSQL_SYSVAR(stats_sample_pages),
1240
   MYSQL_SYSVAR(adaptive_hash_index),
1241
   MYSQL_SYSVAR(replication_delay),
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
1242
@@ -11427,6 +11510,8 @@
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
1243
 i_s_innodb_cmp_reset,
1244
 i_s_innodb_cmpmem,
1245
 i_s_innodb_cmpmem_reset,
1246
+i_s_innodb_table_stats,
1247
+i_s_innodb_index_stats,
1248
 i_s_innodb_patches
1249
 mysql_declare_plugin_end;
1250
 
106 by kinoyasu
Port Yasufumi maintaining patches to 5.1.50:
1251
diff -ruN a/storage/innodb_plugin/handler/i_s.cc b/storage/innodb_plugin/handler/i_s.cc
1252
--- a/storage/innodb_plugin/handler/i_s.cc	2010-08-27 16:13:11.075059060 +0900
1253
+++ b/storage/innodb_plugin/handler/i_s.cc	2010-08-27 16:16:49.253982474 +0900
70.2.1 by kinoyasu
fix bug576041, bug592007, bug607449
1254
@@ -45,6 +45,7 @@
1255
 #include "btr0btr.h" /* for btr_page_get_index_id */
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
1256
 #include "trx0rseg.h" /* for trx_rseg_struct */
1257
 #include "trx0sys.h" /* for trx_sys */
1258
+#include "dict0dict.h" /* for dict_sys */
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
1259
 }
1260
 
1261
 static const char plugin_author[] = "Innobase Oy";
133 by kinoyasu
port maintainer-Yasufumi patches for 5.1.52
1262
@@ -2603,3 +2604,347 @@
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
1263
 	/* void* */
1264
 	STRUCT_FLD(__reserved1, NULL)
1265
 };
1266
+
1267
+/***********************************************************************
1268
+*/
1269
+static ST_FIELD_INFO	i_s_innodb_table_stats_info[] =
1270
+{
1271
+	{STRUCT_FLD(field_name,		"table_schema"),
1272
+	 STRUCT_FLD(field_length,	NAME_LEN),
1273
+	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
1274
+	 STRUCT_FLD(value,		0),
1275
+	 STRUCT_FLD(field_flags,	0),
1276
+	 STRUCT_FLD(old_name,		""),
1277
+	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1278
+
1279
+	{STRUCT_FLD(field_name,		"table_name"),
1280
+	 STRUCT_FLD(field_length,	NAME_LEN),
1281
+	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
1282
+	 STRUCT_FLD(value,		0),
1283
+	 STRUCT_FLD(field_flags,	0),
1284
+	 STRUCT_FLD(old_name,		""),
1285
+	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1286
+
1287
+	{STRUCT_FLD(field_name,		"rows"),
1288
+	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
1289
+	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
1290
+	 STRUCT_FLD(value,		0),
1291
+	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
1292
+	 STRUCT_FLD(old_name,		""),
1293
+	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1294
+
1295
+	{STRUCT_FLD(field_name,		"clust_size"),
1296
+	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
1297
+	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
1298
+	 STRUCT_FLD(value,		0),
1299
+	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
1300
+	 STRUCT_FLD(old_name,		""),
1301
+	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1302
+
1303
+	{STRUCT_FLD(field_name,		"other_size"),
1304
+	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
1305
+	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
1306
+	 STRUCT_FLD(value,		0),
1307
+	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
1308
+	 STRUCT_FLD(old_name,		""),
1309
+	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1310
+
1311
+	{STRUCT_FLD(field_name,		"modified"),
1312
+	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
1313
+	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
1314
+	 STRUCT_FLD(value,		0),
1315
+	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
1316
+	 STRUCT_FLD(old_name,		""),
1317
+	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1318
+
1319
+	END_OF_ST_FIELD_INFO
1320
+};
1321
+
1322
+static ST_FIELD_INFO	i_s_innodb_index_stats_info[] =
1323
+{
1324
+	{STRUCT_FLD(field_name,		"table_schema"),
1325
+	 STRUCT_FLD(field_length,	NAME_LEN),
1326
+	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
1327
+	 STRUCT_FLD(value,		0),
1328
+	 STRUCT_FLD(field_flags,	0),
1329
+	 STRUCT_FLD(old_name,		""),
1330
+	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1331
+
1332
+	{STRUCT_FLD(field_name,		"table_name"),
1333
+	 STRUCT_FLD(field_length,	NAME_LEN),
1334
+	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
1335
+	 STRUCT_FLD(value,		0),
1336
+	 STRUCT_FLD(field_flags,	0),
1337
+	 STRUCT_FLD(old_name,		""),
1338
+	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1339
+
1340
+	{STRUCT_FLD(field_name,		"index_name"),
1341
+	 STRUCT_FLD(field_length,	NAME_LEN),
1342
+	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
1343
+	 STRUCT_FLD(value,		0),
1344
+	 STRUCT_FLD(field_flags,	0),
1345
+	 STRUCT_FLD(old_name,		""),
1346
+	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1347
+
1348
+	{STRUCT_FLD(field_name,		"fields"),
1349
+	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
1350
+	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
1351
+	 STRUCT_FLD(value,		0),
1352
+	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
1353
+	 STRUCT_FLD(old_name,		""),
1354
+	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1355
+
1356
+	{STRUCT_FLD(field_name,		"row_per_keys"),
1357
+	 STRUCT_FLD(field_length,	256),
1358
+	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
1359
+	 STRUCT_FLD(value,		0),
1360
+	 STRUCT_FLD(field_flags,	0),
1361
+	 STRUCT_FLD(old_name,		""),
1362
+	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1363
+
1364
+	{STRUCT_FLD(field_name,		"index_size"),
1365
+	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
1366
+	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
1367
+	 STRUCT_FLD(value,		0),
1368
+	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
1369
+	 STRUCT_FLD(old_name,		""),
1370
+	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1371
+
1372
+	{STRUCT_FLD(field_name,		"leaf_pages"),
1373
+	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
1374
+	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
1375
+	 STRUCT_FLD(value,		0),
1376
+	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
1377
+	 STRUCT_FLD(old_name,		""),
1378
+	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1379
+
1380
+	END_OF_ST_FIELD_INFO
1381
+};
1382
+
1383
+static
1384
+int
1385
+i_s_innodb_table_stats_fill(
1386
+/*========================*/
1387
+	THD*		thd,
1388
+	TABLE_LIST*	tables,
1389
+	COND*		cond)
1390
+{
1391
+	TABLE*	i_s_table	= (TABLE *) tables->table;
1392
+	int	status	= 0;
1393
+	dict_table_t*	table;
1394
+
1395
+	DBUG_ENTER("i_s_innodb_table_stats_fill");
1396
+
1397
+	/* deny access to non-superusers */
1398
+	if (check_global_access(thd, PROCESS_ACL)) {
1399
+		DBUG_RETURN(0);
1400
+	}
1401
+
1402
+	mutex_enter(&(dict_sys->mutex));
1403
+
1404
+	table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
1405
+
1406
+	while (table) {
1407
+		char	buf[NAME_LEN * 2 + 2];
1408
+		char*	ptr;
1409
+
1410
+		if (table->stat_clustered_index_size == 0) {
1411
+			table = UT_LIST_GET_NEXT(table_LRU, table);
1412
+			continue;
1413
+		}
1414
+
1415
+		buf[NAME_LEN * 2 + 1] = 0;
1416
+		strncpy(buf, table->name, NAME_LEN * 2 + 1);
1417
+		ptr = strchr(buf, '/');
1418
+		if (ptr) {
1419
+			*ptr = '\0';
1420
+			++ptr;
1421
+		} else {
1422
+			ptr = buf;
1423
+		}
1424
+
1425
+		field_store_string(i_s_table->field[0], buf);
1426
+		field_store_string(i_s_table->field[1], ptr);
1427
+		i_s_table->field[2]->store(table->stat_n_rows);
1428
+		i_s_table->field[3]->store(table->stat_clustered_index_size);
1429
+		i_s_table->field[4]->store(table->stat_sum_of_other_index_sizes);
1430
+		i_s_table->field[5]->store(table->stat_modified_counter);
1431
+
1432
+		if (schema_table_store_record(thd, i_s_table)) {
1433
+			status = 1;
1434
+			break;
1435
+		}
1436
+
1437
+		table = UT_LIST_GET_NEXT(table_LRU, table);
1438
+	}
1439
+
1440
+	mutex_exit(&(dict_sys->mutex));
1441
+
1442
+	DBUG_RETURN(status);
1443
+}
1444
+
1445
+static
1446
+int
1447
+i_s_innodb_index_stats_fill(
1448
+/*========================*/
1449
+	THD*		thd,
1450
+	TABLE_LIST*	tables,
1451
+	COND*		cond)
1452
+{
1453
+	TABLE*	i_s_table	= (TABLE *) tables->table;
1454
+	int	status	= 0;
1455
+	dict_table_t*	table;
1456
+	dict_index_t*	index;
1457
+
1458
+	DBUG_ENTER("i_s_innodb_index_stats_fill");
1459
+
1460
+	/* deny access to non-superusers */
1461
+	if (check_global_access(thd, PROCESS_ACL)) {
1462
+		DBUG_RETURN(0);
1463
+	}
1464
+
1465
+	mutex_enter(&(dict_sys->mutex));
1466
+
1467
+	table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
1468
+
1469
+	while (table) {
1470
+		if (table->stat_clustered_index_size == 0) {
1471
+			table = UT_LIST_GET_NEXT(table_LRU, table);
1472
+			continue;
1473
+		}
1474
+
1475
+		ib_int64_t	n_rows = table->stat_n_rows;
1476
+
1477
+		if (n_rows < 0) {
1478
+			n_rows = 0;
1479
+		}
1480
+
1481
+		index = dict_table_get_first_index(table);
1482
+
1483
+		while (index) {
1484
+			char	buff[256+1];
1485
+			char	row_per_keys[256+1];
1486
+			char	buf[NAME_LEN * 2 + 2];
1487
+			char*	ptr;
1488
+			ulint	i;
1489
+
1490
+			buf[NAME_LEN * 2 + 1] = 0;
1491
+			strncpy(buf, table->name, NAME_LEN * 2 + 1);
1492
+			ptr = strchr(buf, '/');
1493
+			if (ptr) {
1494
+				*ptr = '\0';
1495
+				++ptr;
1496
+			} else {
1497
+				ptr = buf;
1498
+			}
1499
+
1500
+			field_store_string(i_s_table->field[0], buf);
1501
+			field_store_string(i_s_table->field[1], ptr);
1502
+			field_store_string(i_s_table->field[2], index->name);
1503
+			i_s_table->field[3]->store(index->n_uniq);
1504
+
1505
+			row_per_keys[0] = '\0';
9 by kinoyasu
port for 5.1.47-1.0.8
1506
+
1507
+			/* It is remained optimistic operation still for now */
1508
+			//dict_index_stat_mutex_enter(index);
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
1509
+			if (index->stat_n_diff_key_vals) {
1510
+				for (i = 1; i <= index->n_uniq; i++) {
1511
+					ib_int64_t	rec_per_key;
1512
+					if (index->stat_n_diff_key_vals[i]) {
1513
+						rec_per_key = n_rows / index->stat_n_diff_key_vals[i];
1514
+					} else {
1515
+						rec_per_key = n_rows;
1516
+					}
1517
+					ut_snprintf(buff, 256, (i == index->n_uniq)?"%llu":"%llu, ",
1518
+						 rec_per_key);
1519
+					strncat(row_per_keys, buff, 256 - strlen(row_per_keys));
1520
+				}
1521
+			}
9 by kinoyasu
port for 5.1.47-1.0.8
1522
+			//dict_index_stat_mutex_exit(index);
1523
+
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
1524
+			field_store_string(i_s_table->field[4], row_per_keys);
1525
+
1526
+			i_s_table->field[5]->store(index->stat_index_size);
1527
+			i_s_table->field[6]->store(index->stat_n_leaf_pages);
1528
+
1529
+			if (schema_table_store_record(thd, i_s_table)) {
1530
+				status = 1;
1531
+				break;
1532
+			}
1533
+
1534
+			index = dict_table_get_next_index(index);
1535
+		}
1536
+
1537
+		if (status == 1) {
1538
+			break;
1539
+		}
1540
+
1541
+		table = UT_LIST_GET_NEXT(table_LRU, table);
1542
+	}
1543
+
1544
+	mutex_exit(&(dict_sys->mutex));
1545
+
1546
+	DBUG_RETURN(status);
1547
+}
1548
+
1549
+static
1550
+int
1551
+i_s_innodb_table_stats_init(
1552
+/*========================*/
1553
+	void*   p)
1554
+{
1555
+	DBUG_ENTER("i_s_innodb_table_stats_init");
1556
+	ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
1557
+
1558
+	schema->fields_info = i_s_innodb_table_stats_info;
1559
+	schema->fill_table = i_s_innodb_table_stats_fill;
1560
+
1561
+	DBUG_RETURN(0);
1562
+}
1563
+
1564
+static
1565
+int
1566
+i_s_innodb_index_stats_init(
1567
+/*========================*/
1568
+	void*	p)
1569
+{
1570
+	DBUG_ENTER("i_s_innodb_index_stats_init");
1571
+	ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
1572
+
1573
+	schema->fields_info = i_s_innodb_index_stats_info;
1574
+	schema->fill_table = i_s_innodb_index_stats_fill;
1575
+
1576
+	DBUG_RETURN(0);
1577
+}
1578
+
1579
+UNIV_INTERN struct st_mysql_plugin	i_s_innodb_table_stats =
1580
+{
1581
+	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
1582
+	STRUCT_FLD(info, &i_s_info),
1583
+	STRUCT_FLD(name, "INNODB_TABLE_STATS"),
1584
+	STRUCT_FLD(author, plugin_author),
1585
+	STRUCT_FLD(descr, "InnoDB table statistics in memory"),
1586
+	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
1587
+	STRUCT_FLD(init, i_s_innodb_table_stats_init),
1588
+	STRUCT_FLD(deinit, i_s_common_deinit),
1589
+	STRUCT_FLD(version, 0x0100 /* 1.0 */),
1590
+	STRUCT_FLD(status_vars, NULL),
1591
+	STRUCT_FLD(system_vars, NULL),
1592
+	STRUCT_FLD(__reserved1, NULL)
1593
+};
1594
+
1595
+UNIV_INTERN struct st_mysql_plugin	i_s_innodb_index_stats =
1596
+{
1597
+	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
1598
+	STRUCT_FLD(info, &i_s_info),
1599
+	STRUCT_FLD(name, "INNODB_INDEX_STATS"),
1600
+	STRUCT_FLD(author, plugin_author),
1601
+	STRUCT_FLD(descr, "InnoDB index statistics in memory"),
1602
+	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
1603
+	STRUCT_FLD(init, i_s_innodb_index_stats_init),
1604
+	STRUCT_FLD(deinit, i_s_common_deinit),
1605
+	STRUCT_FLD(version, 0x0100 /* 1.0 */),
1606
+	STRUCT_FLD(status_vars, NULL),
1607
+	STRUCT_FLD(system_vars, NULL),
1608
+	STRUCT_FLD(__reserved1, NULL)
1609
+};
106 by kinoyasu
Port Yasufumi maintaining patches to 5.1.50:
1610
diff -ruN a/storage/innodb_plugin/handler/i_s.h b/storage/innodb_plugin/handler/i_s.h
1611
--- a/storage/innodb_plugin/handler/i_s.h	2010-08-27 15:59:21.754987936 +0900
1612
+++ b/storage/innodb_plugin/handler/i_s.h	2010-08-27 16:16:49.255984731 +0900
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
1613
@@ -38,5 +38,7 @@
1614
 extern struct st_mysql_plugin	i_s_innodb_cmpmem_reset;
1615
 extern struct st_mysql_plugin	i_s_innodb_patches;
1616
 extern struct st_mysql_plugin	i_s_innodb_rseg;
1617
+extern struct st_mysql_plugin	i_s_innodb_table_stats;
1618
+extern struct st_mysql_plugin	i_s_innodb_index_stats;
1619
 
1620
 #endif /* i_s_h */
106 by kinoyasu
Port Yasufumi maintaining patches to 5.1.50:
1621
diff -ruN a/storage/innodb_plugin/handler/innodb_patch_info.h b/storage/innodb_plugin/handler/innodb_patch_info.h
1622
--- a/storage/innodb_plugin/handler/innodb_patch_info.h	2010-08-27 16:15:55.197404531 +0900
1623
+++ b/storage/innodb_plugin/handler/innodb_patch_info.h	2010-08-27 16:16:49.249142399 +0900
1624
@@ -35,5 +35,6 @@
1625
 {"innodb_expand_import","convert .ibd file automatically when import tablespace","the files are generated by xtrabackup export mode.","http://www.percona.com/docs/wiki/percona-xtradb"},
1626
 {"innodb_dict_size_limit","Limit dictionary cache size","Variable innodb_dict_size_limit in bytes","http://www.percona.com/docs/wiki/percona-xtradb"},
1627
 {"innodb_split_buf_pool_mutex","More fix of buffer_pool mutex","Spliting buf_pool_mutex and optimizing based on innodb_opt_lru_count","http://www.percona.com/docs/wiki/percona-xtradb"},
1628
+{"innodb_stats","Additional features about InnoDB statistics/optimizer","","http://www.percona.com/docs/wiki/percona-xtradb"},
1629
 {NULL, NULL, NULL, NULL}
1630
 };
1631
diff -ruN a/storage/innodb_plugin/include/dict0boot.h b/storage/innodb_plugin/include/dict0boot.h
1632
--- a/storage/innodb_plugin/include/dict0boot.h	2010-08-04 02:24:19.000000000 +0900
1633
+++ b/storage/innodb_plugin/include/dict0boot.h	2010-08-27 16:16:49.260982522 +0900
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
1634
@@ -101,6 +101,7 @@
1635
 #define DICT_COLUMNS_ID		ut_dulint_create(0, 2)
1636
 #define DICT_INDEXES_ID		ut_dulint_create(0, 3)
1637
 #define DICT_FIELDS_ID		ut_dulint_create(0, 4)
1638
+#define DICT_STATS_ID		ut_dulint_create(0, 6)
1639
 /* The following is a secondary index on SYS_TABLES */
1640
 #define DICT_TABLE_IDS_ID	ut_dulint_create(0, 5)
1641
 
65.1.1 by kinoyasu
improve SYS_STATS (for upgreading easily from previous version)
1642
@@ -128,10 +129,13 @@
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
1643
 #define	DICT_HDR_INDEXES	44	/* Root of the index index tree */
1644
 #define	DICT_HDR_FIELDS		48	/* Root of the index field
1645
 					index tree */
1646
+#define	DICT_HDR_STATS		52	/* Root of the stats tree */
1647
 
1648
 #define DICT_HDR_FSEG_HEADER	56	/* Segment header for the tablespace
1649
 					segment into which the dictionary
65.1.1 by kinoyasu
improve SYS_STATS (for upgreading easily from previous version)
1650
 					header is created */
1651
+
1652
+#define	DICT_HDR_XTRADB_MARK	256	/* Flag to distinguish expansion of XtraDB */
1653
 /*-------------------------------------------------------------*/
1654
 
1655
 /* The field number of the page number field in the sys_indexes table
1656
@@ -141,11 +145,15 @@
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
1657
 #define DICT_SYS_INDEXES_TYPE_FIELD	 6
1658
 #define DICT_SYS_INDEXES_NAME_FIELD	 4
1659
 
1660
+#define DICT_SYS_STATS_DIFF_VALS_FIELD	 4
1661
+
1662
 /* When a row id which is zero modulo this number (which must be a power of
1663
 two) is assigned, the field DICT_HDR_ROW_ID on the dictionary header page is
1664
 updated */
65.1.1 by kinoyasu
improve SYS_STATS (for upgreading easily from previous version)
1665
 #define DICT_HDR_ROW_ID_WRITE_MARGIN	256
1666
 
1667
+#define DICT_HDR_XTRADB_FLAG		ut_dulint_create(0x58545241UL,0x44425F31UL)	/* "XTRADB_1" */
1668
+
1669
 #ifndef UNIV_NONINL
1670
 #include "dict0boot.ic"
1671
 #endif
106 by kinoyasu
Port Yasufumi maintaining patches to 5.1.50:
1672
diff -ruN a/storage/innodb_plugin/include/dict0crea.h b/storage/innodb_plugin/include/dict0crea.h
1673
--- a/storage/innodb_plugin/include/dict0crea.h	2010-08-04 02:24:19.000000000 +0900
1674
+++ b/storage/innodb_plugin/include/dict0crea.h	2010-08-27 16:16:49.262982080 +0900
65.1.1 by kinoyasu
improve SYS_STATS (for upgreading easily from previous version)
1675
@@ -53,6 +53,14 @@
1676
 	dict_index_t*	index,	/*!< in: index to create, built as a memory data
1677
 				structure */
1678
 	mem_heap_t*	heap);	/*!< in: heap where created */
1679
+/*********************************************************************//**
1680
+*/
1681
+UNIV_INTERN
1682
+ind_node_t*
1683
+ind_insert_stats_graph_create(
1684
+/*==========================*/
1685
+	dict_index_t*	index,
1686
+	mem_heap_t*	heap);
1687
 /***********************************************************//**
1688
 Creates a table. This is a high-level function used in SQL execution graphs.
1689
 @return	query thread to run next or NULL */
1690
@@ -62,6 +70,13 @@
1691
 /*===================*/
1692
 	que_thr_t*	thr);	/*!< in: query thread */
1693
 /***********************************************************//**
1694
+*/
1695
+UNIV_INTERN
1696
+que_thr_t*
1697
+dict_insert_stats_step(
1698
+/*===================*/
1699
+	que_thr_t*	thr);
1700
+/***********************************************************//**
1701
 Creates an index. This is a high-level function used in SQL execution
1702
 graphs.
1703
 @return	query thread to run next or NULL */
1704
@@ -170,6 +185,7 @@
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
1705
 	ins_node_t*	field_def; /* child node which does the inserts of
1706
 				the field definitions; the row to be inserted
1707
 				is built by the parent node  */
1708
+	ins_node_t*	stats_def;
1709
 	commit_node_t*	commit_node;
1710
 				/* child node which performs a commit after
1711
 				a successful index creation */
65.1.1 by kinoyasu
improve SYS_STATS (for upgreading easily from previous version)
1712
@@ -180,6 +196,7 @@
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
1713
 	dict_table_t*	table;	/*!< table which owns the index */
1714
 	dtuple_t*	ind_row;/* index definition row built */
1715
 	ulint		field_no;/* next field definition to insert */
1716
+	ulint		stats_no;
1717
 	mem_heap_t*	heap;	/*!< memory heap used as auxiliary storage */
1718
 };
1719
 
65.1.1 by kinoyasu
improve SYS_STATS (for upgreading easily from previous version)
1720
@@ -189,6 +206,7 @@
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
1721
 #define	INDEX_CREATE_INDEX_TREE	3
1722
 #define	INDEX_COMMIT_WORK	4
1723
 #define	INDEX_ADD_TO_CACHE	5
1724
+#define	INDEX_BUILD_STATS_COLS	6
1725
 
1726
 #ifndef UNIV_NONINL
1727
 #include "dict0crea.ic"
106 by kinoyasu
Port Yasufumi maintaining patches to 5.1.50:
1728
diff -ruN a/storage/innodb_plugin/include/dict0dict.h b/storage/innodb_plugin/include/dict0dict.h
1729
--- a/storage/innodb_plugin/include/dict0dict.h	2010-08-27 16:11:12.177142545 +0900
1730
+++ b/storage/innodb_plugin/include/dict0dict.h	2010-08-27 16:16:49.263981911 +0900
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
1731
@@ -1057,10 +1057,11 @@
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
1732
 dict_update_statistics(
1733
 /*===================*/
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
1734
 	dict_table_t*	table,		/*!< in/out: table */
1735
-	ibool		only_calc_if_missing_stats);/*!< in: only
1736
+	ibool		only_calc_if_missing_stats,	/*!< in: only
1737
 					update/recalc the stats if they have
1738
 					not been initialized yet, otherwise
1739
 					do nothing */
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
1740
+	ibool		sync);
1741
 /********************************************************************//**
1742
 Reserves the dictionary system mutex for MySQL. */
1743
 UNIV_INTERN
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
1744
@@ -1175,6 +1176,7 @@
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
1745
 	dict_table_t*	sys_columns;	/*!< SYS_COLUMNS table */
1746
 	dict_table_t*	sys_indexes;	/*!< SYS_INDEXES table */
1747
 	dict_table_t*	sys_fields;	/*!< SYS_FIELDS table */
1748
+	dict_table_t*	sys_stats;	/*!< SYS_STATS table */
1749
 };
1750
 #endif /* !UNIV_HOTBACKUP */
1751
 
106 by kinoyasu
Port Yasufumi maintaining patches to 5.1.50:
1752
diff -ruN a/storage/innodb_plugin/include/page0cur.h b/storage/innodb_plugin/include/page0cur.h
1753
--- a/storage/innodb_plugin/include/page0cur.h	2010-08-04 02:24:19.000000000 +0900
1754
+++ b/storage/innodb_plugin/include/page0cur.h	2010-08-27 16:16:49.265984316 +0900
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
1755
@@ -293,6 +293,22 @@
1756
 /*==========================*/
1757
 	buf_block_t*	block,	/*!< in: page */
1758
 	page_cur_t*	cursor);/*!< out: page cursor */
1759
+
1760
+UNIV_INTERN
1761
+void
1762
+page_cur_open_on_nth_user_rec(
1763
+/*==========================*/
1764
+	buf_block_t*	block,	/*!< in: page */
1765
+	page_cur_t*	cursor,	/*!< out: page cursor */
1766
+	ulint		nth);
1767
+
1768
+UNIV_INTERN
1769
+ibool
1770
+page_cur_open_on_rnd_user_rec_after_nth(
1771
+/*==========================*/
1772
+	buf_block_t*	block,	/*!< in: page */
1773
+	page_cur_t*	cursor,	/*!< out: page cursor */
1774
+	ulint		nth);
1775
 #endif /* !UNIV_HOTBACKUP */
1776
 /***********************************************************//**
1777
 Parses a log record of a record insert on a page.
106 by kinoyasu
Port Yasufumi maintaining patches to 5.1.50:
1778
diff -ruN a/storage/innodb_plugin/include/que0que.h b/storage/innodb_plugin/include/que0que.h
1779
--- a/storage/innodb_plugin/include/que0que.h	2010-08-04 02:24:19.000000000 +0900
1780
+++ b/storage/innodb_plugin/include/que0que.h	2010-08-27 16:16:49.266982471 +0900
127 by kinoyasu
port maintainer-Yasufumi patches for 5.1.51
1781
@@ -495,6 +495,8 @@
65.1.1 by kinoyasu
improve SYS_STATS (for upgreading easily from previous version)
1782
 #define QUE_NODE_CALL		31
1783
 #define QUE_NODE_EXIT		32
1784
 
1785
+#define QUE_NODE_INSERT_STATS	34
1786
+
1787
 /* Query thread states */
1788
 #define QUE_THR_RUNNING		1
1789
 #define QUE_THR_PROCEDURE_WAIT	2
106 by kinoyasu
Port Yasufumi maintaining patches to 5.1.50:
1790
diff -ruN a/storage/innodb_plugin/include/rem0cmp.h b/storage/innodb_plugin/include/rem0cmp.h
1791
--- a/storage/innodb_plugin/include/rem0cmp.h	2010-08-04 02:24:19.000000000 +0900
1792
+++ b/storage/innodb_plugin/include/rem0cmp.h	2010-08-27 16:16:49.268976969 +0900
48 by kinoyasu
port for mysql-5.1.48
1793
@@ -169,10 +169,11 @@
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
1794
 				matched fields; when the function returns,
1795
 				contains the value the for current
1796
 				comparison */
1797
-	ulint*		matched_bytes);/*!< in/out: number of already matched
1798
+	ulint*		matched_bytes, /*!< in/out: number of already matched
1799
 				bytes within the first field not completely
1800
 				matched; when the function returns, contains
1801
 				the value for the current comparison */
1802
+	ulint		stats_method);
1803
 /*************************************************************//**
1804
 This function is used to compare two physical records. Only the common
1805
 first fields are compared.
106 by kinoyasu
Port Yasufumi maintaining patches to 5.1.50:
1806
diff -ruN a/storage/innodb_plugin/include/rem0cmp.ic b/storage/innodb_plugin/include/rem0cmp.ic
1807
--- a/storage/innodb_plugin/include/rem0cmp.ic	2010-08-04 02:24:19.000000000 +0900
1808
+++ b/storage/innodb_plugin/include/rem0cmp.ic	2010-08-27 16:16:49.269986562 +0900
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
1809
@@ -87,5 +87,5 @@
1810
 	ulint	match_b		= 0;
1811
 
1812
 	return(cmp_rec_rec_with_match(rec1, rec2, offsets1, offsets2, index,
1813
-				      &match_f, &match_b));
1814
+				      &match_f, &match_b, 0));
1815
 }
106 by kinoyasu
Port Yasufumi maintaining patches to 5.1.50:
1816
diff -ruN a/storage/innodb_plugin/include/row0mysql.h b/storage/innodb_plugin/include/row0mysql.h
1817
--- a/storage/innodb_plugin/include/row0mysql.h	2010-08-04 02:24:19.000000000 +0900
1818
+++ b/storage/innodb_plugin/include/row0mysql.h	2010-08-27 16:16:49.271982518 +0900
77 by kinoyasu
port and adjust the part of the patches to 5.1.49: But query_cache_with_comments.patch, response-time-distribution.patch, mysql_remove_eol_carret.patch, log_connection_error.patch, status_wait_query_cache_mutex.patch and sql_no_fcache.patch were not ported yet. Please port them.
1819
@@ -376,6 +376,14 @@
65.1.1 by kinoyasu
improve SYS_STATS (for upgreading easily from previous version)
1820
 					then checked for not being too
1821
 					large. */
1822
 /*********************************************************************//**
1823
+*/
1824
+UNIV_INTERN
1825
+int
1826
+row_insert_stats_for_mysql(
1827
+/*=======================*/
1828
+	dict_index_t*	index,
1829
+	trx_t*		trx);
1830
+/*********************************************************************//**
1831
 Scans a table create SQL string and adds to the data dictionary
1832
 the foreign key constraints declared in the string. This function
1833
 should be called after the indexes for a table have been created.
106 by kinoyasu
Port Yasufumi maintaining patches to 5.1.50:
1834
diff -ruN a/storage/innodb_plugin/include/srv0srv.h b/storage/innodb_plugin/include/srv0srv.h
1835
--- a/storage/innodb_plugin/include/srv0srv.h	2010-08-27 16:15:55.197989840 +0900
1836
+++ b/storage/innodb_plugin/include/srv0srv.h	2010-08-27 16:16:49.285142419 +0900
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
1837
@@ -192,6 +192,13 @@
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
1838
 extern ibool	srv_innodb_status;
1839
 
1840
 extern unsigned long long	srv_stats_sample_pages;
1841
+extern ulint	srv_stats_method;
1842
+#define SRV_STATS_METHOD_NULLS_EQUAL     0
1843
+#define SRV_STATS_METHOD_NULLS_NOT_EQUAL 1
1844
+#define SRV_STATS_METHOD_IGNORE_NULLS    2
1845
+extern ulint	srv_stats_auto_update;
1846
+extern ulint	srv_stats_update_need_lock;
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
1847
+extern ibool	srv_use_sys_stats_table;
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
1848
 
1849
 extern ibool	srv_use_doublewrite_buf;
1850
 extern ibool	srv_use_checksums;
106 by kinoyasu
Port Yasufumi maintaining patches to 5.1.50:
1851
diff -ruN a/storage/innodb_plugin/page/page0cur.c b/storage/innodb_plugin/page/page0cur.c
1852
--- a/storage/innodb_plugin/page/page0cur.c	2010-08-04 02:24:20.000000000 +0900
1853
+++ b/storage/innodb_plugin/page/page0cur.c	2010-08-27 16:16:49.289982393 +0900
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
1854
@@ -564,6 +564,74 @@
1855
 	} while (rnd--);
1856
 }
1857
 
1858
+UNIV_INTERN
1859
+void
1860
+page_cur_open_on_nth_user_rec(
1861
+/*==========================*/
1862
+	buf_block_t*	block,	/*!< in: page */
1863
+	page_cur_t*	cursor,	/*!< out: page cursor */
1864
+	ulint		nth)
1865
+{
1866
+	ulint	n_recs = page_get_n_recs(buf_block_get_frame(block));
1867
+
1868
+	page_cur_set_before_first(block, cursor);
1869
+
1870
+	if (UNIV_UNLIKELY(n_recs == 0)) {
1871
+
1872
+		return;
1873
+	}
1874
+
1875
+	nth--;
1876
+
1877
+	if (nth >= n_recs) {
1878
+		nth = n_recs - 1;
1879
+	}
1880
+
1881
+	do {
1882
+		page_cur_move_to_next(cursor);
1883
+	} while (nth--);
1884
+}
1885
+
1886
+UNIV_INTERN
1887
+ibool
1888
+page_cur_open_on_rnd_user_rec_after_nth(
1889
+/*==========================*/
1890
+	buf_block_t*	block,	/*!< in: page */
1891
+	page_cur_t*	cursor,	/*!< out: page cursor */
1892
+	ulint		nth)
1893
+{
1894
+	ulint	rnd;
1895
+	ulint	n_recs = page_get_n_recs(buf_block_get_frame(block));
1896
+	ibool	ret;
1897
+
1898
+	page_cur_set_before_first(block, cursor);
1899
+
1900
+	if (UNIV_UNLIKELY(n_recs == 0)) {
1901
+
1902
+		return (FALSE);
1903
+	}
1904
+
1905
+	nth--;
1906
+
1907
+	if (nth >= n_recs) {
1908
+		nth = n_recs - 1;
1909
+	}
1910
+
1911
+	rnd = (ulint) (nth + page_cur_lcg_prng() % (n_recs - nth));
1912
+
1913
+	if (rnd == nth) {
1914
+		ret = TRUE;
1915
+	} else {
1916
+		ret = FALSE;
1917
+	}
1918
+
1919
+	do {
1920
+		page_cur_move_to_next(cursor);
1921
+	} while (rnd--);
1922
+
1923
+	return (ret);
1924
+}
1925
+
1926
 /***********************************************************//**
1927
 Writes the log record of a record insert on a page. */
1928
 static
106 by kinoyasu
Port Yasufumi maintaining patches to 5.1.50:
1929
diff -ruN a/storage/innodb_plugin/que/que0que.c b/storage/innodb_plugin/que/que0que.c
1930
--- a/storage/innodb_plugin/que/que0que.c	2010-08-04 02:24:20.000000000 +0900
1931
+++ b/storage/innodb_plugin/que/que0que.c	2010-08-27 16:16:49.291984923 +0900
65.1.1 by kinoyasu
improve SYS_STATS (for upgreading easily from previous version)
1932
@@ -622,11 +622,21 @@
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
1933
 
1934
 		que_graph_free_recursive(cre_ind->ind_def);
1935
 		que_graph_free_recursive(cre_ind->field_def);
54.4.3 by kinoyasu
sys_stats: adjust for compatibility, bug fix, information_schema INNODB_SYS_STATS
1936
+		if (srv_use_sys_stats_table)
1937
+			que_graph_free_recursive(cre_ind->stats_def);
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
1938
 		que_graph_free_recursive(cre_ind->commit_node);
1939
 
1940
 		mem_heap_free(cre_ind->heap);
65.1.1 by kinoyasu
improve SYS_STATS (for upgreading easily from previous version)
1941
 
1942
 		break;
1943
+	case QUE_NODE_INSERT_STATS:
1944
+		cre_ind = node;
1945
+
1946
+		que_graph_free_recursive(cre_ind->stats_def);
1947
+		que_graph_free_recursive(cre_ind->commit_node);
1948
+
1949
+		mem_heap_free(cre_ind->heap);
1950
+		break;
1951
 	case QUE_NODE_PROC:
1952
 		que_graph_free_stat_list(((proc_node_t*)node)->stat_list);
1953
 
1954
@@ -1139,6 +1149,8 @@
1955
 		str = "CREATE TABLE";
1956
 	} else if (type == QUE_NODE_CREATE_INDEX) {
1957
 		str = "CREATE INDEX";
1958
+	} else if (type == QUE_NODE_INSERT_STATS) {
1959
+		str = "INSERT TO SYS_STATS";
1960
 	} else if (type == QUE_NODE_FOR) {
1961
 		str = "FOR LOOP";
1962
 	} else if (type == QUE_NODE_RETURN) {
1963
@@ -1256,6 +1268,8 @@
1964
 		thr = dict_create_table_step(thr);
1965
 	} else if (type == QUE_NODE_CREATE_INDEX) {
1966
 		thr = dict_create_index_step(thr);
1967
+	} else if (type == QUE_NODE_INSERT_STATS) {
1968
+		thr = dict_insert_stats_step(thr);
1969
 	} else if (type == QUE_NODE_ROW_PRINTF) {
1970
 		thr = row_printf_step(thr);
1971
 	} else {
106 by kinoyasu
Port Yasufumi maintaining patches to 5.1.50:
1972
diff -ruN a/storage/innodb_plugin/rem/rem0cmp.c b/storage/innodb_plugin/rem/rem0cmp.c
1973
--- a/storage/innodb_plugin/rem/rem0cmp.c	2010-08-04 02:24:20.000000000 +0900
1974
+++ b/storage/innodb_plugin/rem/rem0cmp.c	2010-08-27 16:16:49.292984980 +0900
48 by kinoyasu
port for mysql-5.1.48
1975
@@ -866,10 +866,11 @@
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
1976
 				matched fields; when the function returns,
1977
 				contains the value the for current
1978
 				comparison */
1979
-	ulint*		matched_bytes) /*!< in/out: number of already matched
1980
+	ulint*		matched_bytes, /*!< in/out: number of already matched
1981
 				bytes within the first field not completely
1982
 				matched; when the function returns, contains
1983
 				the value for the current comparison */
1984
+	ulint		stats_method)
1985
 {
1986
 	ulint		rec1_n_fields;	/* the number of fields in rec */
1987
 	ulint		rec1_f_len;	/* length of current field in rec */
48 by kinoyasu
port for mysql-5.1.48
1988
@@ -962,7 +963,11 @@
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
1989
 
1990
 				if (rec1_f_len == rec2_f_len) {
1991
 
1992
-					goto next_field;
1993
+					if (stats_method == SRV_STATS_METHOD_NULLS_EQUAL) {
1994
+						goto next_field;
1995
+					} else {
1996
+						ret = -1;
1997
+					}
1998
 
1999
 				} else if (rec2_f_len == UNIV_SQL_NULL) {
2000
 
106 by kinoyasu
Port Yasufumi maintaining patches to 5.1.50:
2001
diff -ruN a/storage/innodb_plugin/row/row0merge.c b/storage/innodb_plugin/row/row0merge.c
2002
--- a/storage/innodb_plugin/row/row0merge.c	2010-08-04 02:24:19.000000000 +0900
2003
+++ b/storage/innodb_plugin/row/row0merge.c	2010-08-27 16:16:49.295984498 +0900
2004
@@ -2021,6 +2021,8 @@
65.1.1 by kinoyasu
improve SYS_STATS (for upgreading easily from previous version)
2005
 		"UPDATE SYS_INDEXES SET NAME=CONCAT('"
2006
 		TEMP_INDEX_PREFIX_STR "', NAME) WHERE ID = :indexid;\n"
2007
 		"COMMIT WORK;\n"
2008
+		/* Drop the statistics of the index. */
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
2009
+		"DELETE FROM SYS_STATS WHERE INDEX_ID = :indexid;\n"
65.1.1 by kinoyasu
improve SYS_STATS (for upgreading easily from previous version)
2010
 		/* Drop the field definitions of the index. */
2011
 		"DELETE FROM SYS_FIELDS WHERE INDEX_ID = :indexid;\n"
2012
 		/* Drop the index definition and the B-tree. */
106 by kinoyasu
Port Yasufumi maintaining patches to 5.1.50:
2013
diff -ruN a/storage/innodb_plugin/row/row0mysql.c b/storage/innodb_plugin/row/row0mysql.c
2014
--- a/storage/innodb_plugin/row/row0mysql.c	2010-08-04 02:24:20.000000000 +0900
2015
+++ b/storage/innodb_plugin/row/row0mysql.c	2010-08-27 16:16:49.304981955 +0900
127 by kinoyasu
port maintainer-Yasufumi patches for 5.1.51
2016
@@ -862,6 +862,9 @@
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
2017
 
2018
 	table->stat_modified_counter = counter + 1;
2019
 
2020
+	if (!srv_stats_auto_update)
2021
+		return;
2022
+
2023
 	/* Calculate new statistics if 1 / 16 of table has been modified
2024
 	since the last time a statistics batch was run, or if
2025
 	stat_modified_counter > 2 000 000 000 (to avoid wrap-around).
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
2026
@@ -872,7 +875,7 @@
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
2027
 	    || ((ib_int64_t)counter > 16 + table->stat_n_rows / 16)) {
2028
 
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
2029
 		dict_update_statistics(table, FALSE /* update even if stats
2030
-						    are initialized */);
2031
+						    are initialized */, TRUE);
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
2032
 	}
2033
 }
2034
 
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
2035
@@ -2046,6 +2049,45 @@
65.1.1 by kinoyasu
improve SYS_STATS (for upgreading easily from previous version)
2036
 }
2037
 
2038
 /*********************************************************************//**
2039
+*/
2040
+UNIV_INTERN
2041
+int
2042
+row_insert_stats_for_mysql(
2043
+/*=======================*/
2044
+	dict_index_t*	index,
2045
+	trx_t*		trx)
2046
+{
2047
+	ind_node_t*	node;
2048
+	mem_heap_t*	heap;
2049
+	que_thr_t*	thr;
2050
+	ulint		err;
2051
+
2052
+	ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
2053
+
2054
+	trx->op_info = "try to insert rows to SYS_STATS";
2055
+
2056
+	trx_start_if_not_started(trx);
2057
+	trx->error_state = DB_SUCCESS;
2058
+
2059
+	heap = mem_heap_create(512);
2060
+
2061
+	node = ind_insert_stats_graph_create(index, heap);
2062
+
2063
+	thr = pars_complete_graph_for_exec(node, trx, heap);
2064
+
2065
+	ut_a(thr == que_fork_start_command(que_node_get_parent(thr)));
2066
+	que_run_threads(thr);
2067
+
2068
+	err = trx->error_state;
2069
+
2070
+	que_graph_free((que_t*) que_node_get_parent(thr));
2071
+
2072
+	trx->op_info = "";
2073
+
2074
+	return((int) err);
2075
+}
2076
+
2077
+/*********************************************************************//**
2078
 Scans a table create SQL string and adds to the data dictionary
2079
 the foreign key constraints declared in the string. This function
2080
 should be called after the indexes for a table have been created.
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
2081
@@ -2966,7 +3008,7 @@
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
2082
 	dict_table_autoinc_initialize(table, 1);
2083
 	dict_table_autoinc_unlock(table);
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
2084
 	dict_update_statistics(table, FALSE /* update even if stats are
2085
-					    initialized */);
2086
+					    initialized */, TRUE);
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
2087
 
2088
 	trx_commit_for_mysql(trx);
2089
 
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
2090
@@ -3268,6 +3310,8 @@
65.1.1 by kinoyasu
improve SYS_STATS (for upgreading easily from previous version)
2091
 			   "       IF (SQL % NOTFOUND) THEN\n"
2092
 			   "               found := 0;\n"
2093
 			   "       ELSE\n"
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
2094
+			   "               DELETE FROM SYS_STATS\n"
2095
+			   "               WHERE INDEX_ID = index_id;\n"
65.1.1 by kinoyasu
improve SYS_STATS (for upgreading easily from previous version)
2096
 			   "               DELETE FROM SYS_FIELDS\n"
2097
 			   "               WHERE INDEX_ID = index_id;\n"
2098
 			   "               DELETE FROM SYS_INDEXES\n"
106 by kinoyasu
Port Yasufumi maintaining patches to 5.1.50:
2099
diff -ruN a/storage/innodb_plugin/srv/srv0srv.c b/storage/innodb_plugin/srv/srv0srv.c
2100
--- a/storage/innodb_plugin/srv/srv0srv.c	2010-08-27 16:15:55.198987678 +0900
2101
+++ b/storage/innodb_plugin/srv/srv0srv.c	2010-08-27 16:16:49.311984856 +0900
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
2102
@@ -364,6 +364,10 @@
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
2103
 /* When estimating number of different key values in an index, sample
2104
 this many index pages */
2105
 UNIV_INTERN unsigned long long	srv_stats_sample_pages = 8;
2106
+UNIV_INTERN ulint	srv_stats_method = 0;
2107
+UNIV_INTERN ulint	srv_stats_auto_update = 1;
2108
+UNIV_INTERN ulint	srv_stats_update_need_lock = 1;
54.4.1 by kinoyasu
add SYS_STATS system table and innodb_use_sys_stats_table startup option
2109
+UNIV_INTERN ibool	srv_use_sys_stats_table = FALSE;
1 by kinoyasu
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7
2110
 
2111
 UNIV_INTERN ibool	srv_use_doublewrite_buf	= TRUE;
2112
 UNIV_INTERN ibool	srv_use_checksums = TRUE;