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.