The time required for inserting a row is determined by the following factors, where the numbers indicate approximate proportions:
Connecting: (3)
Sending query to server: (2)
Parsing query: (2)
Inserting row: (1 × size of row)
Inserting indexes: (1 × 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
INSERTstatements with multipleVALUESlists to insert several rows at a time. This is considerably faster (many times faster in some cases) than using separate single-rowINSERTstatements. If you are adding data to a nonempty table, you can tune thebulk_insert_buffer_sizevariable to make data insertion even faster. See Section 5.1.3, “Server System Variables”.If multiple clients are inserting a lot of rows, you can get higher speed by using the
INSERT DELAYEDstatement. See Section 12.2.5.2, “INSERT DELAYEDSyntax”.For a
MyISAMtable, you can use concurrent inserts to add rows at the same time thatSELECTstatements are running, if there are no deleted rows in middle of the data file. See Section 7.7.3, “Concurrent Inserts”.When loading a table from a text file, use
LOAD DATA INFILE. This is usually 20 times faster than usingINSERTstatements. See Section 12.2.6, “LOAD DATA INFILESyntax”.-
With some extra work, it is possible to make
LOAD DATA INFILErun even faster for aMyISAMtable when the table has many indexes. Use the following procedure:Optionally create the table with
CREATE TABLE.Execute a
FLUSH TABLESstatement 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 Section 13.5.3.3, “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 that updating the index duringLOAD DATA INFILEbecause it avoids lots of disk seeks. The resulting index tree is also perfectly balanced.Execute a
FLUSH TABLESstatement or a mysqladmin flush-tables command.
LOAD DATA INFILEperforms the preceding optimization automatically if theMyISAMtable 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 theLOAD DATA INFILEstatement.You can also disable or enable the nonunique indexes for a
MyISAMtable by using the following statements rather than myisamchk. If you use these statements, you can skip theFLUSH TABLEoperations:ALTER TABLE
tbl_nameDISABLE KEYS; ALTER TABLEtbl_nameENABLE KEYS; -
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 areINSERTstatements. Explicit locking statements are not needed if you can insert all rows with a singleINSERT.To obtain faster insertions for transactional tables, you should use
START TRANSACTIONandCOMMITinstead ofLOCK TABLES.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.
INSERT,UPDATE, andDELETEoperations 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 aLOCK TABLESfollowed by anUNLOCK 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.INSERTis still much slower for loading data thanLOAD DATA INFILE, even when using the strategies just outlined. To increase performance for
MyISAMtables, for bothLOAD DATA INFILEandINSERT, enlarge the key cache by increasing thekey_buffer_sizesystem variable. See Section 7.9.2, “Tuning Server Parameters”.