| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
INSERT Queries The time to insert a record consists approximately of:
where the numbers are somewhat proportional to the overall time. 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 (B-trees).
Some ways to speed up inserts:
INSERT statements. This is much faster (many times
in some cases) than using separate INSERT statements. If you are adding
data to non-empty table, you may tune up the bulk_insert_buffer_size
variable to make it even faster.
See section bulk_insert_buffer_size.
INSERT DELAYED statement. See section INSERT.
MyISAM tables you can insert rows at the same time
SELECT statements are running if there are no deleted rows in the tables.
LOAD DATA INFILE. This
is usually 20 times faster than using a lot of INSERT statements.
See section LOAD DATA.
LOAD DATA INFILE run even
faster when the table has many indexes. Use the following procedure:
CREATE TABLE. For example, using
mysql or Perl-DBI.
FLUSH TABLES statement or the shell command mysqladmin
flush-tables.
myisamchk --keys-used=0 -rq /path/to/db/tbl_name. This will
remove all usage of all indexes from the table.
LOAD DATA INFILE. This will not
update any indexes and will therefore be very fast.
myisampack
on it to make it smaller. See section 14.1.2.3 Compressed Table Characteristics.
myisamchk -r -q
/path/to/db/tbl_name. This will create 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.
FLUSH TABLES statement or the shell command mysqladmin
flush-tables.
Note that LOAD DATA INFILE also does the above optimization if
you insert into an empty table; the main difference with the above
procedure is that you can let myisamchk allocate much more temporary
memory for the index creation that you may want MySQL to allocate for
every index recreation.
Since MySQL 4.0 you can also use
ALTER TABLE tbl_name DISABLE KEYS instead of
myisamchk --keys-used=0 -rq /path/to/db/tbl_name and
ALTER TABLE tbl_name ENABLE KEYS instead of
myisamchk -r -q /path/to/db/tbl_name. This way you can also skip
FLUSH TABLES steps.
mysql> LOCK TABLES a WRITE; mysql> INSERT INTO a VALUES (1,23),(2,34),(4,33); mysql> INSERT INTO a VALUES (8,26),(6,29); mysql> UNLOCK TABLES; |
The main speed difference is that 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 different INSERT
statements. Locking is not needed if you can insert all rows with a single
statement.
For transactional tables, you should use BEGIN/COMMIT instead of
LOCK TABLES to get a speedup.
Locking will also lower the total time of multi-connection tests, but the maximum wait time for some threads will go up (because they wait for locks). For example:
thread 1 does 1000 inserts thread 2, 3, and 4 does 1 insert thread 5 does 1000 inserts |
If you don't use locking, 2, 3, and 4 will finish before 1 and 5. If you use locking, 2, 3, and 4 probably will not finish before 1 or 5, but the total time should be about 40% faster.
As INSERT, UPDATE, and DELETE operations are very
fast in MySQL, you will obtain better overall performance by
adding locks around everything that does more than about 5 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 1000 rows) to allow other threads access to the table. This
would still result in a nice performance gain.
LOAD DATA INFILE is much faster for loading data.
To get some more speed for both LOAD DATA INFILE and
INSERT, enlarge the key buffer. See section 7.5.2 Tuning Server Parameters.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |