2015-11-22 2 views
1

В таблице My InnoDB содержится около 1 миллиарда записей журнала. Я пытаюсь сделать простой выбор на столе, в результате чего около 30 миллионов строк. Запрос состоит из условия диапазона для поля int, содержащего метку времени.Запрос диапазона с индексом болезненно медленный

Запрос: SELECT * FROM logs WHERE created_at >= 1446422400 AND created_at <= 1447027199

Этот запрос имеет низкую производительность, работает около 6-7 часов, и только получая около 1,000 строк/сек. created_at имеет индекс на нем, а запрос использует индекс. Когда я делаю простой SELECT * FROM logs WHERE id >= xx AND id <= yy, устанавливая xx и yy так, чтобы результирующий набор был почти таким же (30 миллионов строк), производительность велика, работает макс. 10 минут.

Это действительно меня пугает. Почему диапазон на ПК работает так здорово и по индексу так плохо? Как я могу оптимизировать индекс? Несколько дней назад я воссоздал таблицу, поэтому индексы должны быть в порядке.

Некоторые подробнее:

схема Таблица:

| logs | CREATE TABLE `logs` (
    `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, 
    `categoryid` varchar(15) NOT NULL, 
    `type` varchar(15) NOT NULL, 
    `text` varchar(500) NOT NULL, 
    `created_at` int(7) NOT NULL, 
    `status` varchar(45) NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `status_categoryid_type` (`status`,`categoryid`,`type`), 
    KEY `created_at` (`created_at`), 
) ENGINE=InnoDB AUTO_INCREMENT=1335078012 DEFAULT CHARSET=latin1 | 

Объясните:

| id | select_type | table | type | possible_keys | key  | key_len | ref | rows  | Extra     | 
+------+-------------+---------+-------+----------------------------+---------+------+----------+-----------------------+ 
| 1 | SIMPLE  | logs | range | created_at | created_at | 4  | NULL | 31707348 | Using index condition | 

Цель:

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

+0

есть чтение следующего ответа затем пересмотреть ваш единственный кластерный первичный ключ: http://stackoverflow.com/questions/4419499/mysql-and-nosql-help-me-to-choose-the-right-one/4421601#4421601 –

+0

В подобном сценарии я решил эту проблему с производительностью, добавив дополнительные (избыточные) столбцы в таблицу. В вашем случае это могут быть столбцы типа «created_year» и «created_month». Они могут быть заполнены путем вычисления соответствующих значений года и месяца один раз из столбца created_at. Использование этих столбцов в качестве столбцов индекса может значительно повысить производительность, если вы примете свои sql-запросы для использования этих столбцов в качестве предварительных фильтров. – maxhb

+0

Попробуйте найти подсказки индекса запросов и меня поделиться результатами –

ответ

0

Причина, почему запрос по id работает так быстро, скорее всего, потому, что MySQL создает кластерный индекс для id, потому что это первичный ключ, а индекс created_at не является кластерным, потому что created_at не является первичным ключом.

Я не уверен, почему разница настолько велика, так как даты created_at являются, скорее всего, такими же последовательными, как и id, но, судя по всему, это так.

Итак, попробуйте следующее:

SELECT id FROM logs WHERE created_at >= 1446422400 LIMIT 1 

(присвоить результат ID1)

SELECT id FROM logs WHERE created_at <= 1447027199 ORDER BY id DESC LIMIT 1 

(присвоить результат id2)

SELECT * FROM logs WHERE id >= id1 AND id <= id2 
+0

Спасибо за ваш ответ.Фактически, 'created_at' в моем случае немного вводит в заблуждение, потому что это не только дата создания записи, но и когда она обновляется в последний раз. Это приводит к« фрагментации »данных, а не в партии. Также из-за этого ваше предложение не работает для меня. :(Могу ли я сказать MySQL, чтобы класть ключ 'created_at' тоже? Или это плохой способ? – karot

+0

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

+0

Ничего себе, ладно. На самом деле 1000 строк/сек действительно недостаточно для моего использования case. Может ли разбиение таблицы дать какие-либо улучшения производительности? – karot

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