Задавайте вопросы, мы ответим
Вы не зашли.
Страниц: 1
Добрый день. Есть
Date1 типа DATE
Date2 типа DATE
Делаю запрос
... WHERE CAST(NOW() AS DATE) BETWEEN Date1 AND Date2
EXPLAIN показывает полный перебор таблицы. Пытался делать индексы как отдельно по Date1 и Date2, так и составной индекс (Date1 + Date2) - индексы не используются. Причем, даже в possible_keys их нет.
Пока делаю
WHERE Date1 >= CAST( NOW( ) AS DATE ) AND Date2 <= CAST( NOW( ) AS DATE )
- так используется хотя бы один индекс и перебор уже не all, а range. Но чувствую, что я что-то не так делаю
Подскажите, пожалуйста, как правильно использовать индексы в данной ситуации?
Неактивен
Хм, я что-то не то спросил или это прописные истины, который должен знать каждый?
Пробовал искать в документации - не нашел.
Отредактированно Magz (28.01.2009 13:11:36)
Неактивен
1. Лучше использовать CURDATE() вместо каста.
2. Вы не сможете построить простого решения этой проблемы. Дело в том, что сравнение >=
автоматически подразумевает, что текущий индекс будет использоваться в виде range.
Соответственно, если этот range выбирает половину таблицы - по второй половине таблицы
будет производиться where с отсеиванием результатов. Как правило, в таких случаях придумывают
какие-то способы денормализации таблиц. Сходу, впрочем, придумать такой способ для всех случаев
не могу.
Неактивен
1. Спасибо, изменил.
2. А если вместо "<=" и ">=" использовать строгое "<" и ">"?
Как правило, в таких случаях придумывают
какие-то способы денормализации таблиц. Сходу, впрочем, придумать такой способ для всех случаев
не могу.
Спасибо за участие! Самое главное - это то, что Вы указали направление, куда "копать"!
Неактивен
Сделал
... WHERE Date1 < DATE_SUB(CURDATE(), INTERVAL +1 DAY) AND Date2 > DATE_SUB(CURDATE(), INTERVAL -1 DAY)
Запрос стал использвать объединенный индекс (Date1, Date2). Однако, все равно в explain Using temporary; Using filesort. Можно ли как-то оценить, какой индекс использовать лучше - по одному полю или по двум? Или вообще в данном случае разницы не будет?
Отредактированно Magz (28.01.2009 21:10:16)
Неактивен
Ха! Я разобрался в своей ситуации Я использую ORDER BY RAND() - как только убрал случайную сортировку, сразу пропали Using temporary; Using filesort. Видимо, в данном случае дешевле сделать случайную выборку из PHP.
Неактивен
Не верится, что ключ используется целиком Покажете, что получилось?
Неактивен
paulus написал:
Не верится, что ключ используется целиком Покажете, что получилось?
Нет, ключ целиком так и не используется. Просто, в реальной жизни была несколько другая задача. У меня запрос выбирает данные из трех таблиц:
mysql> EXPLAIN SELECT o.id, o.Caption, o.Body, o.URL, o.URLText, b.`URL_to` url_stat, b.`id_Banner` id_stat -> FROM `context_Objects` o -> JOIN context_Areas a ON a.id_ContextObject = o.id -> AND a.id_ContextArea =10 -> JOIN realto_Banners b ON b.id_Banner = o.id_Banner -> WHERE o.StartDate < CURDATE( ) -> AND o.FinishDate > CURDATE( ) -> ORDER BY RAND( ) -> LIMIT 0 , 4; +----+-------------+-------+--------+------------------------------------+------------------+---------+------------------------+------+----------------------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+--------+------------------------------------+------------------+---------+------------------------+------+----------------------------------------------+ | 1 | SIMPLE | o | range | PRIMARY,id_Banner,context_TwoDates | context_TwoDates | 3 | NULL | 41 | Using where; Using temporary; Using filesort | | 1 | SIMPLE | a | ref | ContextIndex | ContextIndex | 8 | db_realto3.o.id,const | 1 | Using index | | 1 | SIMPLE | b | eq_ref | PRIMARY | PRIMARY | 4 | db_realto3.o.id_Banner | 1 | | +----+-------------+-------+--------+------------------------------------+------------------+---------+------------------------+------+----------------------------------------------+ 3 rows in set (0.00 sec)
Увидав Using temporary; Using filesort я стал разбираться с индексами на данную таблицу, стал моделировать ситуации, когда идет выборка по датам. Не смог найти оптимального решения для индексирования и задал вопрос. Потом, я продолжил опыты и убрав ORDER BY RAND() я добился того, что Using temporary; Using filesort ушли в небытие:
mysql> EXPLAIN SELECT o.id, o.Caption, o.Body, o.URL, o.URLText, b.`URL_to` url_stat, b.`id_Banner` id_stat -> FROM `context_Objects` o -> JOIN context_Areas a ON a.id_ContextObject = o.id -> AND a.id_ContextArea =10 -> JOIN realto_Banners b ON b.id_Banner = o.id_Banner -> WHERE o.StartDate < CURDATE( ) -> AND o.FinishDate > CURDATE( ) -> LIMIT 0 , 4; +----+-------------+-------+--------+------------------------------------+--------------+---------+-------------------------------+------+--------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+--------+------------------------------------+--------------+---------+-------------------------------+------+--------------------------+ | 1 | SIMPLE | a | index | ContextIndex | ContextIndex | 8 | NULL | 106 | Using where; Using index | | 1 | SIMPLE | o | eq_ref | PRIMARY,id_Banner,context_TwoDates | PRIMARY | 4 | db_realto3.a.id_ContextObject | 1 | Using where | | 1 | SIMPLE | b | eq_ref | PRIMARY | PRIMARY | 4 | db_realto3.o.id_Banner | 1 | | +----+-------------+-------+--------+------------------------------------+--------------+---------+-------------------------------+------+--------------------------+ 3 rows in set (0.00 sec)
Собственно, свою проблему в данном случае я решил. Но проблема с индексацией дат и периодов осталась. Я еще создам отдельный пост - оптимизирую сейчас сервис "Расписание", там вообще аховая ситуация Но это чуть позже
Неактивен
Страниц: 1