Bug #60961 | show tables very slow when not in system disk cache | ||
---|---|---|---|
Submitted: | 23 Apr 2011 18:59 | Modified: | 17 May 2012 5:37 |
Reporter: | Galt Barber | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | MySQL Server | Severity: | S2 (Serious) |
Version: | 5.6, 5.5, 5.1 | OS: | Any |
Assigned to: | CPU Architecture: | Any | |
Tags: | Contribution, regression, show tables, slow, uncached |
[23 Apr 2011 18:59]
Galt Barber
[28 Apr 2011 21:41]
Galt Barber
Turns out that the problem exists in mysql 5.1. So here are the versions which exhibit the problem: 5.1 YES 5.5 YES These do not have the problem. 4.x NO 5.0 NO
[28 Apr 2011 21:44]
Galt Barber
More on testing: After clearing the system disk cache, we run show tables on a large database. Since there are 3 files for each table, it looks like you are opening each file, and causing the system to read in the first 4k block from each. I suggest you stop doing that. It's pointless and slow and you don't do it for information_schema, so obviously it's not really necessary.
[30 Apr 2011 0:40]
Galt Barber
Even more testing results: You are reading the entire .frm file for each table in 5.1 and 5.5 during show tables. Even though we have no security requiring column-level checks. My guess is that somehow while goofing around with I_S in 5.1 you accidentally entangled show-tables in your slow .frm fetching. Although you later fixed I_S in 5.5, you still left show-tables crippled by wanting to read each and every .frm file, even though you don't bother I_S with that overhead.
[3 May 2011 1:42]
Galt Barber
I have been looking at the source code. You are checking the .frm file to find out if it is a table or a view. Well, unless you have specified FULL in your show tables command, you don't care whether it is a table or a view, and thus it should not even be checking. It used to work in 5.0, so something has been broken since then in checking the FULL flag for SHOW TABLES. Please fix this soon. Reading thousands of .frm files for no reason is a big waste. I see that you ignore temporary files by having a temp-file prefix for all the names of your temp-tables. It probably would be a good idea to give all the views a different prefix too so you can know what they are without having to open every single one of them.
[3 May 2011 6:26]
Galt Barber
You need to add a check for lex->verbose which gets set when FULL is specified with the "show full tables" command. (mysql5.0 has this check, but 5.1 on up do not) If full is not specified, do not do add field[3], and especially, do not call the dd_frm_type .frm checker. Note this function is static and only called when schema_table_idx == SCH_TABLE_NAMES which means the SHOW-TABLES command. (From sql/sql_show.cc:) static int fill_schema_table_names(THD *thd, TABLE *table, LEX_STRING *db_name, LEX_STRING *table_name, bool with_i_schema) { if (lex->verbose) // added by me { if (with_i_schema) { table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"), system_charset_info); } else { enum legacy_db_type not_used; char path[FN_REFLEN + 1]; (void) build_table_filename(path, sizeof(path) - 1, db_name->str, table_name->str, reg_ext, 0); switch (dd_frm_type(thd, path, ¬_used)) { case FRMTYPE_ERROR: table->field[3]->store(STRING_WITH_LEN("ERROR"), system_charset_info); break; case FRMTYPE_TABLE: table->field[3]->store(STRING_WITH_LEN("BASE TABLE"), system_charset_info); break; case FRMTYPE_VIEW: table->field[3]->store(STRING_WITH_LEN("VIEW"), system_charset_info); break; default: DBUG_ASSERT(0); } if (thd->is_error() && thd->stmt_da->sql_errno() == ER_NO_SUCH_TABLE) { thd->clear_error(); return 0; } } } // added by me if (schema_table_store_record(thd, table)) return 1; return 0; }
[4 May 2011 16:31]
Galt Barber
I am trying to add the contribution tag.
[4 May 2011 16:44]
Galt Barber
Trying to expand the version to show multiple versions affected.
[4 May 2011 18:41]
Sveta Smirnova
Thank you for the report. Verified as described. To repeat: create database bug60961, then for i in `seq 1 1 13500`; do ./bin/mysql -uroot -S /tmp/mysql_ssmirnova.sock bug60961 -A -e "create table t_$i(f1 int) engine=myisam;"; done then 5.0: $time ./bin/mysql -uroot -S /tmp/mysql_ssmirnova.sock bug60961 -A -e "show tables" >/dev/null real 0m1.827s user 0m0.016s sys 0m0.004s 5.1: $time ./bin/mysql -uroot -S /tmp/mysql_ssmirnova.sock bug60961 -A -e "show tables" >/dev/null real 0m8.793s user 0m0.023s sys 0m0.004s 5.5.10 $time ./s1 bug60961 -A -e "show tables" >/dev/null real 0m8.965s user 0m0.017s sys 0m0.006s trunk: $time ./bin/mysql -uroot -S /tmp/mysql_ssmirnova.sock bug60961 -A -e "show tables" >/dev/null real 0m8.656s user 0m0.032s sys 0m0.005s
[22 Sep 2011 23:28]
Galt Barber
Jeez, 141 days with no action is kind of pathetic. I even gave you the fix, and it's only one line of code: if (lex->verbose) Add that to the place noted above and you have one bug fixed.
[17 May 2012 2:37]
Paul DuBois
Noted in 5.1.64, 5.5.25, 5.6.6 changelogs. SHOW TABLES was very slow unless the required information was already in the disk cache.
[17 May 2012 5:37]
Galt Barber
Very cool that you applied the fix! Now we can use mysql 5.5. Thanks a bunch!
[28 Mar 2014 19:39]
Bob Hansen
Thanks for fixing this! It's common for me to have 20+ databases installed at any given time and switching between them was slow. This has saved me a lot of waiting.