[mysql] Вставить 8 млн строк с проверкой на совпадения.

SCIF32

Задача простая - есть куча слов, нужно придумать наиболее быстрый способ создать таблицу из таких строк:
(<id> , <слово>, <количество>)
таблица сейчас обявляется так:

CREATE TABLE words
(
id int PRIMARY KEY auto_increment,
text char(100) NOT NULL, index using hash (text
count int NOT NULL
);

движок видимо по-умолчанию - MyIsam.
для слов выбран хеш, ибо имхо он быстрее, да и особых требований к запросам по этому полю нет.
Слова вставляются так:
1. Проверяется есть ли слово, или нет (по равенству с text).
2. Если есть, то апдейтится счетчик. (по id)
3. Если нет, то вставляется новая запись.
Не вдаваясь в подробности характеристик железа, скажу, что это все скорее тормозит, чем нет.
mysqld на сколько я помню настроен по-умолчанию,
Может есть способ ускорить процесс, и каким образом?

dgaf

разбить кучу на кучки и послать в `sort | uniq -c` :)
потом кучки вставлять почти тем же способом.
можно распараллелить

SCIF32

спасибо,
поэкспериментирую с этим

ermsoft

text char(100) NOT NULL, index using hash (text
Эээ.

















Storage Engine Allowable Index Types

MyISAM
BTREE, RTREE

InnoDB
BTREE

MEMORY/HEAP
HASH, BTREE

NDB
HASH


(хотя признаюсь, вообще никогда типами индексов пользоваться не доводилось).
Дальше, text char(100) - это что? text или char? На самом деле тут нужен varchar(100) скорее. TEXT - это почти blob, и хранится особым образом.
И индекс конечно же нужен UNIQUE.
Если это разовое действие и данные лежат в файле, то правда sort | uniq -c самый быстрый способ (особенно если слова в большинстве своём простые и в итоге останется тысяч 50 уникальных). Если данные уже в mysql, то можно и INSERT words(text, count) SELECT word, COUNT(1) FROM src GROUP BY word, он тот же самый sort | uniq сделает в своих временных файлах или на памяти. (хотя скорее всего, GNU-шные утилиты всё равно быстрее). (и sort_buffer_size прибавить надо будет, если хочется побыстрее и память свободная есть).
Если процесс инкрементальный, то надо думать про INSERT words(text) VALUES(.........) ON DUPLICATE KEY UPDATE count = count + 1; большими порциями values за раз. И на InnoDB перейти.
Да, и самое главное. Ненастроенный mysqld - это кошмар. Хотя и не такой кошмар, как ненастроенный mysqld c innodb.
PS: про кодировку не забудь, в зависимости от выставленной collation слова с большой и маленькой буквы могут считаться одинаковыми или разными :)

SCIF32

спасибо за просвещение, буду думать :)
(хотя признаюсь, вообще никогда типами индексов пользоваться не доводилось).
таблица - жесть, а главное, mysql при создании не ругался.
как оказалось - создавалось всеравно btree.
Дальше, text char(100) - это что? text или char? На самом деле тут нужен varchar(100) скорее. TEXT - это почти blob, и хранится особым образом.
И индекс конечно же нужен UNIQUE.
text char(100) - это переменная с именем "text" и типом char(100) :grin:. varchar я так понимаю дает уменьшение размеров базы, но ускорения и уменьшения индекса - нет.
UNIQE - тоже скорее относится к целостности данных и т.п., но на скорость не особо влияет.
PS: про кодировку не забудь, в зависимости от выставленной collation слова с большой и маленькой буквы могут считаться одинаковыми или разными :)
Спасибо, не забыл, просто здесь из запроса убрал, чтобы не отвелекала. :)

pitrik2

varchar я так понимаю дает уменьшение размеров базы, но ускорения и уменьшения индекса - нет
раз одно преимущество нашел (хоть и не суть важное) то зачем тогда использовать char?
UNIQE - тоже скорее относится к целостности данных и т.п., но на скорость не особо влияет.
по идее с юник должна чуток быстрее работать

SCIF32

естественно, в итоге я поменял на varchar
зы
с uniqe пробовал - но его вличние не заметно - погрешность больше

ermsoft

Скорость доступа к диску и даже к оперативе - больший боттлнек, чем процессорные такты, так что чем меньше база, тем быстрее чтение => тем больше теоретически производительность :)
C unique можно insert on duplicate key update, а без него только в два запроса (ещё и рискуя нарваться на race condition).
PS. Про text char я ступил, ага... Была у меня колонка fetch, потом долго раскаивался, когда на 5-й mysql база перехала.
Оставить комментарий
Имя или ник:
Комментарий: