Я пишу приложение, которое использует MySQL для сохранения хэш-данных файла в простой DB с одной таблицей. Я создал следующим образом:MySQL медленнее производительность * с * индексами?
CREATE DATABASE IF NOT EXISTS hash_db;
CREATE TABLE IF NOT EXISTS hash_db.main_tbl
(
sha256 CHAR(64) PRIMARY KEY ,
sha1 CHAR(40) UNIQUE KEY ,
md5 CHAR(32) UNIQUE KEY ,
created DATETIME ,
modified DATETIME ,
size BIGINT ,
ext VARCHAR(260) ,
path TEXT(32768) ,
new_record BOOL
)
ENGINE = MyISAM
CREATE UNIQUE INDEX sha256_idx ON hash_db.main_tbl (sha256)
CREATE UNIQUE INDEX sha1_idx ON hash_db.main_tbl (sha1)
CREATE UNIQUE INDEX md5_idx ON hash_db.main_tbl (md5)
Тогда я делаю только простые выбирает и вставки формы:
SELECT * FROM hash_db.main_tbl WHERE
sha256 = '...' OR
sha1 = '...' OR
md5 = '...'
INSERT INTO hash_db.main_tbl
(sha256, sha1, md5, created, modified, size, ext, path, new_record) VALUES
(
'...' ,
'...' ,
'...' ,
FROM_UNIXTIME(...) ,
FROM_UNIXTIME(...) ,
... ,
'...' ,
'...' ,
TRUE
)
данных является в значительной степени случайным и единственность вероятность очень высока (не что это должно иметь значение или должно быть?). Первый вопрос, нормально ли, что InnoDB намного медленнее (~ 7 раз медленнее), чем MyISAM для такого использования? Я читал, что это должно быть наоборот. Пробовали с 512M innodb_buffer_pool_size, без разницы.
Вторым ... Я тестировал с индексами и без индексов (MyISAM), а версия с индексами на самом деле медленнее. Эти фактические данные о производительности, как измерено с помощью моего приложения (с помощью счетчиков производительности в C):
With indexes:
Selects per second: 393.7
Inserts per second: 1056.1
Without indexes:
Selects per second: 585.3
Inserts per second: 1480.9
данные я получаю воспроизводят. Я тестировал с расширенным key_buffer_size (32M, по умолчанию 8M).
Что я делаю неправильно или не хватает?
================================================================================================================================== ==================================
Edited после того, как предложение Гордон Линофф в:
У меня есть попробовал с UNION ALL, и я действительно уменьшаю производительность, 70 выборок в секунду точно. Выход из EXPLAIN выглядит следующим образом:
EXPLAIN EXTENDED SELECT * FROM main_hash_db.main_tbl WHERE md5 = '...'
+----+-------------+----------+-------+---------------+------+---------+-------+------+----------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------+-------+---------------+------+---------+-------+------+----------+-------+
| 1 | SIMPLE | main_tbl | const | md5 | md5 | 97 | const | 1 | 100.00 | NULL |
+----+-------------+----------+-------+---------------+------+---------+-------+------+----------+-------+
EXPLAIN EXTENDED SELECT * FROM main_hash_db.main_tbl WHERE md5 = '...' UNION ALL SELECT * FROM main_hash_db.main_tbl WHERE sha1 = '...'
+----+--------------+------------+-------+-----------------------+------+---------+-------+------+----------+-----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+--------------+------------+-------+-----------------------+------+---------+-------+------+----------+-----------------+
| 1 | PRIMARY | main_tbl | const | md5 | md5 | 97 | const | 1 | 100.00 | NULL |
| 2 | UNION | main_tbl | const | sha1,sha1_idx,md5_idx | sha1 | 121 | const | 1 | 100.00 | NULL |
| NULL | UNION RESULT | <union1,2> | ALL | NULL | NULL | NULL | NULL | NULL | NULL | Using temporary |
+----+--------------+------------+-------+-----------------------+------+---------+-------+------+----------+-----------------+
EXPLAIN EXTENDED SELECT * FROM main_hash_db.main_tbl WHERE md5 = '...' UNION ALL SELECT * FROM main_hash_db.main_tbl WHERE sha1 = '...' UNION ALL SELECT * FROM main_hash_db.main_tbl WHERE sha256 = '...'
+----+--------------+--------------+-------+-----------------------+---------+---------+-------+------+----------+-----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+--------------+--------------+-------+-----------------------+---------+---------+-------+------+----------+-----------------+
| 1 | PRIMARY | main_tbl | const | md5 | md5 | 97 | const | 1 | 100.00 | NULL |
| 2 | UNION | main_tbl | const | sha1,sha1_idx,md5_idx | sha1 | 121 | const | 1 | 100.00 | NULL |
| 3 | UNION | main_tbl | const | PRIMARY,sha256_idx | PRIMARY | 192 | const | 1 | 100.00 | NULL |
| NULL | UNION RESULT | <union1,2,3> | ALL | NULL | NULL | NULL | NULL | NULL | NULL | Using temporary |
+----+--------------+--------------+-------+-----------------------+---------+---------+-------+------+----------+-----------------+
Что заставило меня видеть, я была ошибка в создании индекса (я создавал два отдельных индексов для столбца «sha1»). Но после исправления вещи все еще медленно (~ 70 выбирает в секунду), а вот выход для EXPLAIN
:
+----+--------------+--------------+-------+--------------------+---------+---------+-------+------+----------+-----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+--------------+--------------+-------+--------------------+---------+---------+-------+------+----------+-----------------+
| 1 | PRIMARY | main_tbl | const | md5,md5_idx | md5 | 97 | const | 1 | 100.00 | NULL |
| 2 | UNION | main_tbl | const | sha1,sha1_idx | sha1 | 121 | const | 1 | 100.00 | NULL |
| 3 | UNION | main_tbl | const | PRIMARY,sha256_idx | PRIMARY | 192 | const | 1 | 100.00 | NULL |
| NULL | UNION RESULT | <union1,2,3> | ALL | NULL | NULL | NULL | NULL | NULL | NULL | Using temporary |
+----+--------------+--------------+-------+--------------------+---------+---------+-------+------+----------+-----------------+
==================== ================================================== ==========
Третья редакция в дальнейшем обсуждении (см. Ниже). Вот EXPLAIN
выход для исходного запроса (никакие дополнительные индексы не определены, база данных создается, как описано выше):
explain extended select path from main_hash_db.main_tbl where sha256 = '...' or md5 = '...' or sha1 = '...' ;
+----+-------------+----------+-------------+------------------+------------------+------------+------+------+----------+--------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------+-------------+------------------+------------------+------------+------+------+----------+--------------------------------------------+
| 1 | SIMPLE | main_tbl | index_merge | PRIMARY,sha1,md5 | PRIMARY,md5,sha1 | 192,97,121 | NULL | 3 | 100.00 | Using union(PRIMARY,md5,sha1); Using where |
+----+-------------+----------+-------------+------------------+------------------+------------+------+------+----------+--------------------------------------------+
Производительность, измеренная с помощью моего приложения:
Selects per second: 500.6
Inserts per second: 1394.8
Это результат 3 выбирает (выдается отдельно, а не с UNION
):
Selects per second: 2525.1
Inserts per second: 1584.3
Я пробовал ваше предложение, и это на самом деле ухудшает производительность, m получает 70 выборок в секунду. Я предполагаю, что индексы на самом деле используются, но происходит много дисков, а не кеш-память RAM. Я на что-то? Должен ли я увеличить некоторые буферы в my.ini? (какие?) – user3671607
Возможно, вам понадобятся лучшие буферы, но вы посмотрели планы 'explain'. –
Гордон, я редактировал оригинальный вопрос с выходами EXPLAIN. – user3671607