2016-04-20 2 views
0
CREATE TABLE campaigns (
    domain varchar(50) DEFAULT NULL, 
    campaign_id varchar(50) DEFAULT NULL, 
    node_id varchar(50) DEFAULT NULL, 
    subscriber_id varchar(50) DEFAULT NULL, 
    message varchar(21000) DEFAULT NULL, 
    log_time datetime DEFAULT NULL, 
    log_type varchar(50) DEFAULT NULL, 
    campaign_name varchar(500) DEFAULT NULL 

    KEY `campid_domain_logtype_logtime_subid_index` (`campaign_id`,`domain`,`log_type`,`log_time`,`subscriber_id`), 
    KEY `domain_logtype_logtime_index` (`domain`,`log_type`,`log_time`) 

) 

Вышеупомянутая схема нашей таблицы в MySql. Одна кампания может иметь несколько узлов.Как MySql обрабатывает составной индекс

Индекс campid_domain_logtype_logtime_subid_index отлично работает с отчетами специальной кампании w.r.t.

Недавно мы добавили node_id в эту таблицу, теперь нам нужны отчеты w.r.t конкретного узла.

Так что теперь я планирую изменить наш индекс покрытия, как следующие для поддержки как на уровне кампании и уровень узла сообщает

campid_nodeid_domain_logtype_logtime_subid_index.

Пример запроса для отчетов о конкретной кампании

SELECT log_type, 
     count(DISTINCT subscriber_id) AS count, 
     count(subscriber_id) AS total 
FROM stats.campaign_logs USE INDEX(campid_domain_logtype_logtime_subid_index) 
where domain = 'aaa' AND campaign_id='12345' AND 
    log_type in ('EMAIL_SENT','EMAIL_OPENED','EMAIL_CLICKED') 
    AND log_time BETWEEN CONVERT_TZ('2016-03-13 00:00:00','+01:30','+00:00') AND CONVERT_TZ('2016-04-13 23:59:59','+01:30','+00:00') 
GROUP BY log_type; 

Пример запроса для отчетов по конкретному идентификатору узла конкретной кампании

SELECT 
    log_type, 
    count(DISTINCT subscriber_id) AS count, 
    count(subscriber_id) AS total 
FROM stats.campaign_logs USE INDEX(campid_domain_logtype_logtime_subid_index) 
where domain='aaa' AND campaign_id='12345' AND 
     node_id = '56789' and 
     log_type in ('EMAIL_SENT','EMAIL_OPENED','EMAIL_CLICKED') 
     AND log_time BETWEEN CONVERT_TZ('2016-03-13 00:00:00','+01:30','+00:00') AND CONVERT_TZ('2016-04-13 23:59:59','+01:30','+00:00') 
GROUP BY log_type; 

Так что мой вопрос этот новый индекс эффективно удовлетворить наши как-то запросы если нет, предложите подходящие индексы.

ОБНОВЛЕНИЕ: Распределение

данных в таблице

1 Домен может иметь несколько кампаний, например 20

1 кампания может иметь несколько узлов, например 10

1 кампанию может иметь несколько типов журналов, например 50

1 Кампания может га у много абонентов, например, 100 000

1 Кампания может иметь много журнальных времен, так как мы используем mysql now() при хранении журнала.

UPDATE

Благодаря

ответ

0

По вашим вопросам, вы должны создать следующий индекс

KEY `campid_domain_logtype_logtime_subid_index` (
    `campaign_id`, 
    `domain`, 
    `log_time`, 
    `node_id`, 
    `subscriber_id` 
); 

campaign_id и log_time используются всегда, node_id только в некоторых случаях.

Не уверен, что вы должны оставили domain и subscriber_id

Не видеть их в запросах.

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

Обновлено

Согласно нашим коммуникациям в комментариях

  • Идентификатор кампании является первичным столбцом
  • доменом является вторым. Попробуйте играть, может быть, вы должны удалить его
  • время Log для диапазона выбора
  • идентификатора узла для вас конкретных запросов

Если вы часто используете subscriber_id в запросах - добавьте его.

И я бы удалил log_type.

Как вариант, попробуйте создать следующий индекс:

Campaign id, Log time, Node ID (subscriber_id ?) 
+0

Не могли бы вы добавить избирательность каждого поля - Сколько уникальных значений у него есть –

+0

сколько доменов в вашем столе? –

+0

сейчас arround 4k. некоторые домены имеют только несколько строк и некоторые домены, имеющие большое количество строк в таблице. – Rams

0

Основных правил для построения лучшего показателя:

  1. включает столбец (ы) с '=', в любом порядке;
  2. включают еще одну колонку, предпочтительно диапазон.

Для первого запроса вам понадобится INDEX(domain, campaign_id, log_time). log_type мешает; не включайте его.

(добавлено) INDEX(campaign_id, node_id, domain, log_time) необходим для «нового» запроса.

В обоих случаях log_time должен быть последним; другие столбцы могут быть в любом порядке. Изменение порядка может помочь в других запросах. Ни один индекс не является оптимальным для обоих запросов.

Тогда не используйте USE INDEX; это может иметь неприятные последствия.

More cookbook tips.

Лучшее решение является более сложным: создавать и поддерживать сводные таблицы различных счетчиков/сумм, которые часто необходимы. (Возможно, используя 30-минутные интервалы времени.) Предостережение: COUNT(DISTINCT ...) не может обрабатываться в сводной таблице.

Почему эти идентификаторы VARCHAR(50), а не INT UNSIGNED? Вы также выиграете от нормализации других полей, таких как domain. log_type может быть 1-байтным ENUM.

Вам действительно нужны все столбцы, которые должны быть NULLable?

Является ли любая комбинация этих столбцов уникальной? InnoDB действительно любит иметь PRIMARY KEY.

+0

Спасибо за ваш ответ. Я пробовал с вашим предлагаемым индексом, но его время, чтобы получить результаты, и вы не ответили на мой индекс столбца node_id. вы могли бы ответить на него. – Rams

+0

Исходный запрос требует одного индекса; новый запрос с node_id нуждается в другом. (Я добавил пару абзацев к моему ответу.) –

+0

Сколько строк затрагивается для запуска этих запросов? Если это миллионы, возможно, нам стоит поговорить о Сводных таблицах. –

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