2014-09-02 2 views
0

Я пишу приложение, которое использует 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 

ответ

3

Во-первых, можно было бы ожидать insert без индекса будет быстрее. Там нет никакой тайны. Индекс не должен поддерживаться. Фактически, при больших вставках хорошая стратегия часто заключается в том, чтобы сначала отбросить индексы, внести вставки и затем перестроить их.

select более хлопотно. В конце концов, именно там вы хотите, чтобы индексы использовались.Ваш запрос:

SELECT * 
FROM hash_db.main_tbl 
WHERE sha256 = '...' OR 
     sha1 = '...' OR 
     md5 = '...'; 

Это худший случай использования индекса. Вам нужно посмотреть на explain, чтобы узнать, как используются индексы.

Моя рекомендация, чтобы написать запрос, как это: (. Или использовать union, если вы действительно хотите, чтобы устранить дубликаты)

SELECT * 
FROM hash_db.main_tbl 
WHERE sha256 = '...' 
UNION ALL 
SELECT * 
FROM hash_db.main_tbl 
sha1 = '...' 
UNION ALL 
SELECT * 
FROM hash_db.main_tbl 
WHERE md5 = '...'; 

Это должно воспользоваться каждым индексом для каждого подзапроса и должно дать вам производительность, которую вы хотите.

+0

Я пробовал ваше предложение, и это на самом деле ухудшает производительность, m получает 70 выборок в секунду. Я предполагаю, что индексы на самом деле используются, но происходит много дисков, а не кеш-память RAM. Я на что-то? Должен ли я увеличить некоторые буферы в my.ini? (какие?) – user3671607

+0

Возможно, вам понадобятся лучшие буферы, но вы посмотрели планы 'explain'. –

+0

Гордон, я редактировал оригинальный вопрос с выходами EXPLAIN. – user3671607

0

вы снизить производительность и замедлить поток с базой ваших данных, потому что вы будете создавать большое количество индексов

каждый раз, когда вставка один кортеж, который s означает, что вы будете увеличивать непосредственно число индекса в вашей системе SGBD

, когда вы делаете выбор, это похоже на исследование .. с широким числом индексов делает некоторые проблемы в Системе; как приоритет, и у вас будет большое количество приоритетов, у вас есть 1000 кортежей в вашей БД с 3000 индексами

У каждого программного обеспечения есть свой метод управления индексами; и вы должны знать, как осваивать индексы, тогда вы можете нажать систему в своем максимальном потенциале. вы можете использовать, например, trrigrs с индексами, чтобы сделать хороший баланс.

Смежные вопросы