The time required for inserting a record is determined by the following factors, where the numbers indicate approximate proportions:
Connecting: (3)
Sending query to server: (2)
Parsing query: (2)
Inserting record: (1 x size of record)
Inserting indexes: (1 x number of indexes)
Closing: (1)
This does not take into consideration the initial overhead to open tables, which is done once for each concurrently running query.
The size of the table slows down the insertion of indexes by log
N, assuming B-tree indexes.
You can use the following methods to speed up inserts:
If you are inserting many rows from the same client at the
same time, use INSERT statements with
multiple VALUES lists to insert several
rows at a time. This is considerably faster (many times
faster in some cases) than using separate single-row
INSERT statements. If you are adding data
to a non-empty table, you may tune the
bulk_insert_buffer_size variable to make
data insertion even faster. See
Sección 5.3.3, “Variables de sistema del servidor”.
If you are inserting a lot of rows from different clients,
you can get higher speed by using the INSERT
DELAYED statement. See Sección 13.2.4, “Sintaxis de INSERT”.
With MyISAM tables you can insert rows at
the same time that SELECT statements are
running if there are no deleted rows in the tables.
When loading a table from a text file, use LOAD
DATA INFILE. This is usually 20 times faster than
using a lot of INSERT statements. See
Sección 13.2.5, “Sintaxis de LOAD DATA INFILE”.
With some extra work, it is possible to make LOAD
DATA INFILE run even faster when the table has
many indexes. Use the following procedure:
Optionally create the table with CREATE
TABLE.
Execute a FLUSH TABLES statement or a
mysqladmin flush-tables command.
Use myisamchk --keys-used=0 -rq
/path/to/db/tbl_name.
This removes all use of indexes for the table.
Insert data into the table with LOAD DATA
INFILE. This does not update any indexes and
therefore is very fast.
If you intend only to read from the table in the future, use myisampack to compress it. See Sección 14.1.3.3, “Características de las tablas comprimidas”.
Re-create the indexes with myisamchk -r -q
/path/to/db/tbl_name.
This creates the index tree in memory before writing it
to disk, which is much faster because it avoids lots of
disk seeks. The resulting index tree is also perfectly
balanced.
Execute a FLUSH TABLES statement or a
mysqladmin flush-tables command.
Note that LOAD DATA INFILE also performs
the preceding optimization if you insert into an empty
MyISAM table; the main difference is that
you can let myisamchk allocate much more
temporary memory for the index creation than you might want
the server to allocate for index re-creation when it
executes the LOAD DATA INFILE statement.
In MySQL 5.0, you can also use ALTER TABLE
instead of myisamchk --keys-used=0 -rq
tbl_name DISABLE KEYS/path/to/db/tbl_name
and ALTER TABLE instead of myisamchk -r -q
tbl_name
ENABLE KEYS/path/to/db/tbl_name.
In this way, you can also skip the FLUSH
TABLES steps.
You can speed up INSERT operations that
are done with multiple statements by locking your tables:
LOCK TABLES a WRITE; INSERT INTO a VALUES (1,23),(2,34),(4,33); INSERT INTO a VALUES (8,26),(6,29); UNLOCK TABLES;
This benefits performance because the index buffer is
flushed to disk only once, after all
INSERT statements have completed.
Normally there would be as many index buffer flushes as
there are INSERT statements. Explicit
locking statements are not needed if you can insert all rows
with a single statement.
For transactional tables, you should use
BEGIN and COMMIT
instead of LOCK TABLES to obtain faster
insertions.
Locking also lowers the total time of multiple-connection tests, although the maximum wait time for individual connections might go up because they wait for locks. For example:
Connection 1 does 1000 inserts Connections 2, 3, and 4 do 1 insert Connection 5 does 1000 inserts
If you don't use locking, connections 2, 3, and 4 finish before 1 and 5. If you use locking, connections 2, 3, and 4 probably do not finish before 1 or 5, but the total time should be about 40% faster.
INSERT, UPDATE, and
DELETE operations are very fast in MySQL,
but you can obtain better overall performance by adding
locks around everything that does more than about five
inserts or updates in a row. If you do very many inserts in
a row, you could do a LOCK TABLES
followed by an UNLOCK TABLES once in a
while (about each 1,000 rows) to allow other threads access
to the table. This would still result in a nice performance
gain.
INSERT is still much slower for loading
data than LOAD DATA INFILE, even when
using the strategies just outlined.
To get some more speed for MyISAM tables,
for both LOAD DATA INFILE and
INSERT, enlarge the key cache by
increasing the key_buffer_size system
variable. See Sección 7.5.2, “Afinar parámetros del servidor”.
Ésta es una traducción del manual de referencia de MySQL, que puede encontrarse en dev.mysql.com. El manual de referencia original de MySQL está escrito en inglés, y esta traducción no necesariamente está tan actualizada como la versión original. Para cualquier sugerencia sobre la traducción y para señalar errores de cualquier tipo, no dude en dirigirse a mysql-es@vespito.com.
