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