2014-10-16 4 views
1

Во-первых, извините, если используемые условия не являются правильными. Я не профессионал mySQL.Добавить индекс в колонку

У меня есть таблица вроде этого:

CREATE TABLE `accesses` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `time` int(11) DEFAULT NULL, 
    `accessed_at` datetime DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `index_accesses_on_accessed_at` (`accessed_at`) 
) ENGINE=InnoDB AUTO_INCREMENT=9278483 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci 

Эта таблица имеет 10.000.000 строк в нем. Я использую его для создания диаграмм с такими запросами:

SELECT SUM(time) AS value, DATE(created_at) AS date 
FROM `accesses` 
GROUP BY date; 

Этот запрос очень длинный (более 1 минуты). Я делаю много других запросов (с AVG, MIN или MAX вместо SUM или с WHERE на определенный день или месяц, или GROUP BY HOUR(created_at), и т.д. ...)

Я хочу, чтобы оптимизировать его. Лучшая идея заключается в том, чтобы добавить несколько столбцов с избыточностью, например DATE(created_at), HOUR(created_at), MONTH(created_at), а затем добавить на нее указатель.

... Является ли это решение хорошим или есть ли другое?

С уважением

+0

Возможно, было бы разумно дать полное объявление таблицы, вывод: 'SHOW CREATE TABLE accesses' – NDM

+0

1 минута hella long для простого запроса выбора, подобного этому, даже с количеством записей, которые у вас есть. Я задал этот вопрос [DatabaseAdministrators] (http://dba.stackexchange.com/). – Alternatex

+0

ну, он 'group' и' sum' на 10 mil records, не ограничивая набор результатов ... – NDM

ответ

2

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

В зависимости от количества данных и частоты запросов это может быть важным ускорением (@Marshall Tigerus слишком сильно переводит его, ИМХО).

Я проверил это путем запуска EXPLAIN:

mysql> explain SELECT SUM(time) AS value, DATE(created_at) AS date FROM `accesses` GROUP BY date\G      *************************** 1. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: accesses 
    partitions: NULL 
     type: ALL 
possible_keys: NULL 
      key: NULL 
     key_len: NULL 
      ref: NULL 
     rows: 1 
    filtered: 100.00 
     Extra: Using temporary; Using filesort 

игнорировать тот факт, что таблица пуста, в моем тесте. Важной частью является Using temporary; Using filesort, которые являются дорогостоящими операциями, особенно если ваша временная таблица становится настолько большой, что MySQL не может поместиться в нее.

Я добавил некоторые столбцы и индексы на них:

mysql> alter table accesses add column cdate date, add key (cdate), 
    add column chour tinyint, add key (chour), 
    add column cmonth tinyint, add key (cmonth); 

mysql> explain SELECT SUM(time) AS value, cdate FROM `accesses` GROUP BY cdate\G 
*************************** 1. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: accesses 
    partitions: NULL 
     type: index 
possible_keys: cdate 
      key: cdate 
     key_len: 4 
      ref: NULL 
     rows: 1 
    filtered: 100.00 
     Extra: NULL 

Временная таблица и FileSort ушли, потому что MySQL знает, что может сделать сканирование индекса для обработки строк в правильном порядке.

+0

Спасибо за этот полный ответ. Мой запрос выполняется менее чем за 400 мс. Ницца ! – pierallard

+0

Рад помочь! Теперь вам нужно написать триггеры для вставки и обновления, чтобы синхронизировать эти сгенерированные столбцы с created_date. –

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