A short while after I fixed the legacy bug that prevented temporary
MyISAM tables from using the dynamic record format, I got an email from Davi
Arnaut @ Twitter. It turned out that Twitter needed to fix the very same
problem, but for the case when INFORMATION_SCHEMA temporary tables use
MyISAM.
In short, INFORMATION_SCHEMA tables provide access to database metadata.
Despite their name, they are more like views than tables: when you query
them, relevant data is gathered from the dictionary and other server
internals, not from tables. The gathered data is stored in a temporary table (memory or MyISAM depending on size) and then returned to the user.
The reason Davi emailed me was to let me know that he had further
improved the fix for temporary MyISAM tables to also enable the use of
dynamic record format for INFORMATION_SCHEMA tables. I usually don't
have huge databases on my development box so the problem of querying
metadata had gone unnoticed. But it turns out that Davi and his
colleagues at Twitter do deal with massive amounts of data :-)
This was one of the queries that caused problems:
SELECT pool_id FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE limit 1;
Showing posts with label temporary table. Show all posts
Showing posts with label temporary table. Show all posts
Friday, May 4, 2012
Wednesday, April 18, 2012
Copying unused bytes is bad (duh!)
Last summer my colleague Marko Mäkelä committed this seemingly innocent performance fix for InnoDB in MySQL 5.6:
Before this, buffers which were used to send VARCHARs from InnoDB to the MySQL server were padded with 0s if the string was shorter than specified by the column. If, e.g., the string "foo" was stored in a VARCHAR(8), InnoDB used to write "3foo00000" to the buffer (the first character - 3 - determines the actual length of the string). However, even though these trailing bytes are not used anywhere, writing 0s to the buffer certainly has a cost. Hence the fix which stops InnoDB from writing them.
Oh my were we up for a ride! All of a sudden Valgrind started barking like this (and similar) for a number of tests:
3581 Marko Makela 2011-08-10
Bug#12835650 VARCHAR maximum length performance impact
row_sel_field_store_in_mysql_format(): Do not pad the unused part of
the buffer reserved for a True VARCHAR column (introduced in 5.0.3).
Add Valgrind instrumentation ensuring that the unused part will be
flagged uninitialized.
Before this, buffers which were used to send VARCHARs from InnoDB to the MySQL server were padded with 0s if the string was shorter than specified by the column. If, e.g., the string "foo" was stored in a VARCHAR(8), InnoDB used to write "3foo00000" to the buffer (the first character - 3 - determines the actual length of the string). However, even though these trailing bytes are not used anywhere, writing 0s to the buffer certainly has a cost. Hence the fix which stops InnoDB from writing them.
Oh my were we up for a ride! All of a sudden Valgrind started barking like this (and similar) for a number of tests:
Thread 19:The modifications we did to the server to remedy the problems can be divided into two categories as described below. In the end, the result was significantly improved performance.
Syscall param pwrite64(buf) points to uninitialised byte(s)
at 0x381C60EEE3: ??? (in /lib64/libpthread-2.12.so)
by 0x84B703: my_pwrite (my_pread.c:162) by 0x86FE6F: mi_nommap_pwrite (mysql_file.h:1203)
by 0x88621B: _mi_write_static_record (mi_statrec.c:65)
by 0x889592: mi_write (mi_write.c:142)
by 0x532085: handler::ha_write_row(unsigned char*) (handler.cc:6043)
by 0x69B7F7: end_write(JOIN*, st_join_table*, bool) (sql_select.cc:20237)
by 0x69A43C: evaluate_join_record(JOIN*, st_join_table*, int)
(sql_select.cc:19187)
by 0x69A8E0: sub_select(JOIN*, st_join_table*, bool) (sql_select.cc:19294)
Subscribe to:
Posts (Atom)