Я пытался решить следующую проблему в течение часа и так и не получил дальнейшее развитие.
Хорошо, у меня есть таблица (MyISAM):
+---------+-------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| http | smallint(3) | YES | MUL | 200 | |
| elapsed | float(6,3) | NO | | NULL | |
| cached | tinyint(1) | YES | | NULL | |
| ip | int(11) | NO | | NULL | |
| date | timestamp | NO | MUL | CURRENT_TIMESTAMP | |
+---------+-------------+------+-----+-------------------+----------------+
Пожалуйста, не обращайте внимания на индексы, я пытался найти решение. Теперь вот мой запрос.
SELECT http,
COUNT( http ) AS count
FROM reqs
WHERE DATE(date) >= cast(date_sub(date(NOW()),interval 24 hour) as datetime)
GROUP BY http
ORDER BY count;
таблица хранит информацию о входящих веб-запросах, поэтому это довольно большая база данных.
+-----------+
| count(id) |
+-----------+
| 782412 |
+-----------+
обратите внимание, что нет лучшего способа установить первичный ключ, так как столбец id будет единственным уникальным идентификатором, который у меня есть. Вышеупомянутый запрос занимает около 0,6-1,6 секунд для запуска.
Какой индекс будет умным? Я полагал, что дата индексации даст мне «плохую» мощность, и поэтому MySQL не будет ее использовать. http также является плохим выбором, поскольку существует только около 20 различных возможных значений.
Спасибо за помощь!
Обновление 1 Я добавил индекс (http, date), как предложил ypercube:
mysql> CREATE INDEX httpDate ON reqs (http, date);
и использовал его запрос, но он выполнялся одинаково плохо. Добавленный индекс:
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| reqs | 0 | PRIMARY | 1 | id | A | 798869 | NULL | NULL | | BTREE | |
| reqs | 1 | httpDate | 1 | http | A | 19 | NULL | NULL | YES | BTREE | |
| reqs | 1 | httpDate | 2 | date | A | 99858 | NULL | NULL | | BTREE | |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
и ОБЪЯСНИТЬ
+----+--------------------+-------+-------+---------------+----------+---------+------+-------+-----------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-------+-------+---------------+----------+---------+------+-------+-----------------------------------------------------------+
| 1 | PRIMARY | r | range | NULL | httpDate | 3 | NULL | 20 | Using index for group-by; Using temporary; Using filesort |
| 2 | DEPENDENT SUBQUERY | ri | ref | httpDate | httpDate | 3 | func | 41768 | Using where; Using index |
+----+--------------------+-------+-------+---------------+----------+---------+------+-------+-----------------------------------------------------------+
Версия сервера MySQL:
mysql> SHOW VARIABLES LIKE "%version%";
+-------------------------+---------------------+
| Variable_name | Value |
+-------------------------+---------------------+
| protocol_version | 10 |
| version | 5.1.73 |
| version_comment | Source distribution |
| version_compile_machine | x86_64 |
| version_compile_os | redhat-linux-gnu |
+-------------------------+---------------------+
5 rows in set (0.00 sec)
источник
http
колонка обнуляется. Я буду расследовать завтра, если найду время.http NOT NULL
) и скопировав в нее все данные (кроме строк с http NULL, конечно.)Ответы:
У меня есть три предложения
ПРЕДЛОЖЕНИЕ № 1: Перепишите запрос
Вы должны переписать запрос следующим образом
или
ГДЕ не должно иметь функции с обеих сторон знака равенства. Наличие даты в левой части знака равенства позволяет оптимизатору запросов использовать индекс против него.
ПРЕДЛОЖЕНИЕ № 2: Индекс поддержки
Я бы также предложил другой индекс
Я предлагаю этот порядок столбцов, потому
date
что все записи будут смежными в индексе. Затем запрос просто собираетhttp
значения без пропусков вhttp
.ПРЕДЛОЖЕНИЕ № 3: больший ключевой буфер (необязательно)
MyISAM использует только кэширование индекса. Так как запрос не должен касаться
.MYD
файла, вы должны использовать немного больший MyISAM Key Buffer.Чтобы установить его на 256M
Затем установите его в
my.cnf
Перезапуск MySQL не требуется
Попробуйте!
источник
Измените тип столбца даты на целое число. Сохраните дату как дату Unix в целом числе. Отметка времени намного больше, чем int. Вы получите от этого какой-то удар.
источник
INT
и другоеTIMESTAMP
нужно 4 байта.