These performance tips supplement the general guidelines for fast inserts in Section 126.96.36.199, “Optimizing INSERT Statements”.
To improve performance when multiple clients insert a lot of rows, use the
INSERT DELAYEDstatement. See Section 188.8.131.52, “INSERT DELAYED Syntax”. This technique works for
MyISAMand some other storage engines, but not
INSERT DELAYEDis deprecated, and will be removed in a future release. Use
MyISAMtable, you can use concurrent inserts to add rows at the same time that
SELECTstatements are running, if there are no deleted rows in middle of the data file. See Section 8.11.3, “Concurrent Inserts”.
With some extra work, it is possible to make
LOAD DATA INFILErun even faster for a
MyISAMtable when the table has many indexes. Use the following procedure:
Use myisamchk --keys-used=0 -rq
/path/to/db/tbl_nameto remove 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 Section 184.108.40.206, “Compressed Table Characteristics”.
Re-create the indexes with myisamchk -rq
/path/to/db/tbl_name. This creates the index tree in memory before writing it to disk, which is much faster than updating the index during
LOAD DATA INFILEbecause it avoids lots of disk seeks. The resulting index tree is also perfectly balanced.
LOAD DATA INFILEperforms the preceding optimization automatically if the
MyISAMtable into which you insert data is empty. The main difference between automatic optimization and using the procedure explicitly 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 INFILEstatement.
tbl_nameDISABLE KEYS; ALTER TABLE
To speed up
INSERToperations that are performed with multiple statements for nontransactional tables, lock 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
INSERTstatements have completed. Normally, there would be as many index buffer flushes as there are
INSERTstatements. Explicit locking statements are not needed if you can insert all rows with a single
Locking also lowers the total time for multiple-connection tests, although the maximum wait time for individual connections might go up because they wait for locks. Suppose that five clients attempt to perform inserts simultaneously as follows:
Connection 1 does 1000 inserts
Connections 2, 3, and 4 do 1 insert
Connection 5 does 1000 inserts
If you do not 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.
DELETEoperations are very fast in MySQL, but you can obtain better overall performance by adding locks around everything that does more than about five successive inserts or updates. If you do very many successive inserts, you could do a
LOCK TABLESfollowed by an
UNLOCK TABLESonce in a while (each 1,000 rows or so) to permit other threads to access table. This would still result in a nice performance gain.