Сравнение производительности большого текста в MySQL ... лучшие практики? - PullRequest
2 голосов
/ 04 февраля 2009

У меня большая таблица (~ 1,5M записей), в которой содержатся текстовые строки различной длины, для которых я выполняю запросы на предмет поиска совпадений:

CREATE TABLE IF NOT EXISTS `shingles` (
  `id` bigint(20) NOT NULL auto_increment,
  `TS` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
  `shingle` varchar(255) NOT NULL,
  `count` int(11) NOT NULL default '0',
  PRIMARY KEY  (`id`),
  KEY `shingle` (`shingle`,`TS`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1571668;

Моя проблема в том, что мне нужно, пока я делаю сравнения с этой таблицей, я постоянно добавляю и удаляю из нее данные, поэтому поддерживать индексы сложно.

Я ищу лучшие практики для своевременного управления вставками при максимизации пропускной способности для выбора. Этот процесс выполняется 24 часа в сутки и должен быть максимально быстрым.

Любая помощь приветствуется.

Обновление: Для пояснения, я делаю однозначные совпадения в столбце 'shingle', а не в текстовом поиске внутри него.

Ответы [ 2 ]

1 голос
/ 16 марта 2009

Во-первых: ваш первичный ключ bigint может убить вас здесь, это очень дорогой тип для поддержки. 1,5 миллиона записей нигде не приближаются к пределу для unsigned int (~ 4,2 миллиарда).

Использование большого int для первичного ключа еще хуже в InnoDB, поскольку он хранит PK для каждой записи в каждом другом индексе, что может частично объяснить проблемы при попытке переключения. Как только вы добавляете и удаляете данные из таблицы, MyISAM облажается при большом количестве одновременных транзакций.

Хитрость, позволяющая обойтись за счет сравнения строк, заключается в том, чтобы хранить crc32 (shingle), а также shingle. Затем вы индексируете этот столбец, но не свой varchar. Пример того, как я могу это сделать ниже:

CREATE TABLE IF NOT EXISTS `shingles` (
  `id` int unsigned NOT NULL auto_increment,
  `TS` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
  `crc` int unsigned not null,
  `shingle` varchar(255) NOT NULL,
  `count` int(11) NOT NULL default '0',
  PRIMARY KEY  (`id`),
  KEY `crc` (`crc`)
)
insert into shingles (crc, shingle, count) values (crc32('testtest'),'testtest',1),(crc32('foobar'),'foobar',4);
select * from shingles where crc = crc32('foobar') and shingle = 'foobar';

Если вы намереваетесь запросить 'ts', добавьте его как второй компонент индекса crc

0 голосов
/ 05 февраля 2009

Для начала используйте InnoDB вместо MyISAM. Это решит проблему выполнения запросов, в то время как вы также делаете вставки.

Возможно, вам придется немного изменить конфигурацию mysql, чтобы использовать память для innodb (innodb_buffer_pool_size вместо key_buffer_size).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...