Правильный индекс для моего запроса MySQL - PullRequest
0 голосов
/ 27 сентября 2011

У меня есть следующая таблица:

  CREATE TABLE `sal_forwarding` (
  `sid` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
  `f_shop` INT(11) NOT NULL,
  `f_offer` INT(11) DEFAULT NULL,
  .
  .
  .
  PRIMARY KEY (`sid`),
  KEY `forwardTime` (`forwardTime`,`f_shop`),
  KEY `forwardTime_2` (`forwardTime`),
  KEY `f_shop` (`f_shop`)
) ENGINE=INNODB AUTO_INCREMENT=10457068 DEFAULT CHARSET=latin1

В этой таблице более 5 миллионов строк.

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

Объясните:

EXPLAIN SELECT 
  f_shop
  , COUNT(sid)
  , SUM(IF(toolbarUser=1,1,0)) 
FROM sal_forwarding 
WHERE DATE(forwardTime) = "2011-09-01" 
GROUP BY f_shop

Результат:

+----+-------------+----------------+-------+---------------+--------+---------+--------+--------+-------------+
| ID | SELECT_TYPE |     TABLE      | TYPE  | POSSIBLE_KEYS |  KEY   | KEY_LEN |  REF   |  ROWS  |    EXTRA    |
+----+-------------+----------------+-------+---------------+--------+---------+--------+--------+-------------+
|    |             |                |       |               |        |         |        |        |             |
| 1  | SIMPLE      | sal_forwarding | index | (NULL)        | f_shop | 4       | (NULL) | 232449 | Using where |
+----+-------------+----------------+-------+---------------+--------+---------+--------+--------+-------------+

1 Ответ

2 голосов
/ 27 сентября 2011

MySQL не может использовать индекс для столбца внутри функции.
Удалите функцию date() из вашего выбора, и MySQL будет использовать индекс.

Вы можете сделать это, изменив определение столбца с forwardtime на DATE
Или вы можете изменить запрос так:

SELECT 
  f_shop
  , COUNT(*) as RowCount
  , SUM(toolbarUser=1) as NumberOfToolbarUsers
FROM sal_forwarding 
WHERE forwardTime BETWEEN '2011-09-01 00:00' AND '2011-09-01 23:59' 
GROUP BY f_shop

Замечания

  • count(*) быстрее, чем count(namedcolumn);
  • (a = 1) => 1, если true, (a = 1) => 0, если false, поэтому if(a=1,1,0) можно сократить;
  • Хорошей идеей будет присвоить псевдонимы вашим агрегатным столбцам, чтобы вы могли обращаться к ним по их псевдонимам позже.
  • Если вы добавите следующий индекс (и удалите индекс forwardtime), ваш запрос будет выполняться еще быстрее. KEY fasttime (forwardTime,f_shop,toolbarUser)
  • Предыдущий пункт особенно актуален для InnoDB, где MySQL будет использовать индекс покрытия, если это возможно, что означает, что он никогда не будет читать саму таблицу для получения данных, если сможет найти все, что ему нужно в индексе.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...