If you have existing tables, and applications that use them,
that you want to convert to InnoDB for better
reliability and scalability, use the following guidelines and
tips. This section assumes most such tables were originally
MyISAM, which was formerly the default.
To get the best performance from InnoDB
tables, you can adjust a number of parameters related to storage
layout.
When you convert MyISAM tables that are
large, frequently accessed, and hold vital data, investigate and
consider the
innodb_file_per_table,
innodb_file_format, and
innodb_page_size configuration
options, and the
ROW_FORMAT
and KEY_BLOCK_SIZE clauses of the
CREATE TABLE statement.
During your initial experiments, the most important setting is
innodb_file_per_table. Enabling
this option before creating new InnoDB tables
ensures that the InnoDB
system tablespace
files do not allocate disk space permanently for all the
InnoDB data. With
innodb_file_per_table enabled,
DROP TABLE and
TRUNCATE TABLE free disk space as
you would expect.
To convert a non-InnoDB table to use
InnoDB use ALTER
TABLE:
ALTER TABLE table_name ENGINE=InnoDB;
Do not convert MySQL system tables in the
mysql database (such as
user or host) to the
InnoDB type. This is an unsupported
operation. The system tables must always be of the
MyISAM type.
You might make an InnoDB table that is a clone of a MyISAM
table, rather than doing the ALTER
TABLE conversion, to test the old and new table
side-by-side before switching.
Create an empty InnoDB table with identical
column and index definitions. Use show create table
to see the
full table_name\GCREATE TABLE statement to
use. Change the ENGINE clause to
ENGINE=INNODB.
To transfer a large volume of data into an empty
InnoDB table created as shown in the previous
section, insert the rows with INSERT INTO
.
innodb_table SELECT * FROM
myisam_table ORDER BY
primary_key_columns
You can also create the indexes for the
InnoDB table after inserting the data.
Historically, creating new secondary indexes was a slow
operation for InnoDB, but now you can create the indexes after
the data is loaded with relatively little overhead from the
index creation step.
If you have UNIQUE constraints on secondary
keys, you can speed up a table import by turning off the
uniqueness checks temporarily during the import operation:
SET unique_checks=0;... import operation ...
SET unique_checks=1;
For big tables, this saves disk I/O because
InnoDB can use its
insert buffer to write
secondary index records as a batch. Be certain that the data
contains no duplicate keys.
unique_checks permits but does
not require storage engines to ignore duplicate keys.
To get better control over the insertion process, you might insert big tables in pieces:
INSERT INTO newtable SELECT * FROM oldtable WHERE yourkey >somethingAND yourkey <=somethingelse;
After all records have been inserted, you can rename the tables.
During the conversion of big tables, increase the size of the
InnoDB buffer pool to reduce disk I/O, to a
maximum of 80% of physical memory. You can also increase the
sizes of the InnoDB log files.
By this point, as already mentioned, you should already have the
innodb_file_per_table option
enabled, so that if you temporarily make several copies of your
data in InnoDB tables, you can recover all
that disk space by dropping unneeded tables afterward.
Whether you convert the MyISAM table directly
or create a cloned InnoDB table, make sure
that you have sufficient disk space to hold both the old and new
tables during the process. InnoDB tables
require more disk space than MyISAM tables.
If an ALTER TABLE operation runs
out of space, it starts a rollback, and that can take hours if
it is disk-bound. For inserts, InnoDB uses
the insert buffer to merge secondary index records to indexes in
batches. That saves a lot of disk I/O. For rollback, no such
mechanism is used, and the rollback can take 30 times longer
than the insertion.
In the case of a runaway rollback, if you do not have valuable
data in your database, it may be advisable to kill the database
process rather than wait for millions of disk I/O operations to
complete. For the complete procedure, see
Section 14.2.5.6, “Starting InnoDB on a Corrupted Database”.
The extra reliability and scalability features of
InnoDB do require more disk storage than
equivalent MyISAM tables. You might change
the column and index definitions slightly, for better space
utilization, reduced I/O and memory consumption when processing
result sets, and better query optimization plans making
efficient use of index lookups.
Consider adding a primary key to any table that does not already have one. Use the smallest practical numeric type based on the maximum projected size of the table. This can make each row slightly more compact, which can yield substantial savings for tens of millions of rows. The space savings are multiplied if the table has any secondary indexes, because the primary key value is repeated in each secondary index entry.
If the table already has a primary key on some longer column,
such as a VARCHAR, consider adding a new
unsigned AUTO_INCREMENT column and switching
the primary key to that, even if that column is not referenced
in queries. This design change can produce substantial space
savings in the secondary indexes. You can designate the former
primary key columns as UNIQUE NOT NULL to
enforce the same constraints as the PRIMARY
KEY clause, that is, to prevent duplicate or null
values across all those columns.
If you do set up a numeric ID column for the primary key, use
that value to cross-reference with related values in any other
tables, particularly for join
queries. For example, rather than accepting a country name as
input and doing queries searching for the same name, do one
lookup to determine the country ID, then do other queries (or a
single join query) to look up relevant information across
several tables. Rather than storing a customer or catalog item
number as a string of digits, potentially using up several
bytes, convert it to a numeric ID for storing and querying. A
4-byte unsigned INT column can
index over 4 billion items (with the US meaning of billion: 1000
million). For the ranges of the different integer types, see
Section 11.2.1, “Integer Types (Exact Value) - INTEGER,
INT, SMALLINT,
TINYINT, MEDIUMINT,
BIGINT”.

User Comments
Add your own comment.