Модераторы: skyboy

Поиск:

Ответ в темуСоздание новой темы Создание опроса
>  MySQL: Выбор с ограичением по дате, Какой запрос производительнее? 
:(
    Опции темы
Sunvas
Дата 29.8.2008, 19:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Соль и сахар
****


Профиль
Группа: Участник
Сообщений: 3388
Регистрация: 12.3.2006
Где: Тосно

Репутация: нет
Всего: 89



Есть таблица с полем типа DATE. Нужно выбирать строки по нему. Есть два запроса с одинаковым результатом:
Код

SELECT `date` FROM `table` WHERE `date` LIKE '2007-05%'

и
Код

SELECT `date` FROM `table` WHERE MONTH(`date`)='5' AND YEAR(`date`)='2007'


По сему вопрос: какой из этих запросов производительнее?


--------------------
Воспитывая детей по своему образу и подобию, родители почему-то надеются, что они будут лучше их.
PM MAIL   Вверх
skyboy
Дата 29.8.2008, 21:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

Репутация: 15
Всего: 260



второй. кавычки вокруг чисолвых констант можно убрать.
------
логика первого: поле(значение поля) приводится к строковому типу, по которому производится поиск с использованием шаблонов(среди строковых функций медленнее like только regexp).
логика второго: вычленяется целочисленное значение из целочисленного значения(видимо, при помощи простых арифметических операций). даже с приведением результата к строковому типу(так как у тебя константы - строковые) все равно должно получаться много быстрее первого варианта. но ключи не используются.
------
мне думается, вариант, использующий возможный ключ по полю `date`, должен выглядеть так:
Код

SELECT `date` 
FROM `table` 
WHERE `date`>= '01-05-2007' AND `date`< '01-06-2007'

PM MAIL   Вверх
Sunvas
Дата 29.8.2008, 21:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Соль и сахар
****


Профиль
Группа: Участник
Сообщений: 3388
Регистрация: 12.3.2006
Где: Тосно

Репутация: нет
Всего: 89



Цитата(skyboy @  29.8.2008,  21:06 Найти цитируемый пост)
мне думается, вариант, использующий возможный ключ по полю `date`, должен выглядеть так:

Дело в том, что мне нужно извлекать даты исходя из поступивших значений значения месяца и года. С первым числом месяца проблем не возникнет:
Код

'`date`>=\''.$y.'-'.$m.'-01\''

Но вот если пихать последним 31:
Код

' AND `date`<=\''.$y.'-'.$m.'-31\''

То может возникнуть абсурд типа 2007-02-31, что будет в таком случае - я не знаю.

Это сообщение отредактировал(а) Sunvas - 29.8.2008, 21:19


--------------------
Воспитывая детей по своему образу и подобию, родители почему-то надеются, что они будут лучше их.
PM MAIL   Вверх
skyboy
Дата 29.8.2008, 23:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

Репутация: 15
Всего: 260



зачем тебе последний день месяца? 
PM MAIL   Вверх
Sunvas
Дата 30.8.2008, 01:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Соль и сахар
****


Профиль
Группа: Участник
Сообщений: 3388
Регистрация: 12.3.2006
Где: Тосно

Репутация: нет
Всего: 89



Чтобы выбрать все строки из таблицы с датой этого месяца и не важно, каким днем.


--------------------
Воспитывая детей по своему образу и подобию, родители почему-то надеются, что они будут лучше их.
PM MAIL   Вверх
skyboy
Дата 30.8.2008, 14:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

Репутация: 15
Всего: 260



я приводил пример. в нем выбираются все записи для "даты конкретного месяца с неважно каким днем". покажи мне, где там используется последний день месяца.
PM MAIL   Вверх
Nigel
Дата 30.8.2008, 21:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


познаю мир
**


Профиль
Группа: Участник
Сообщений: 515
Регистрация: 20.11.2007

Репутация: нет
Всего: 19



А может проще date_format?
Код

... where date_format(`date`, '%Y-%m')='2008-08'

PM MAIL   Вверх
skyboy
Дата 30.8.2008, 21:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

Репутация: 15
Всего: 260



Nigel, вместо работы с целыми числами - преобразование в строку? кхм, к первоначальному вопросу про "запрос производительнее".
PM MAIL   Вверх
Sunvas
Дата 30.8.2008, 22:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Соль и сахар
****


Профиль
Группа: Участник
Сообщений: 3388
Регистрация: 12.3.2006
Где: Тосно

Репутация: нет
Всего: 89



skyboy, в Вашем примере нужно увеличивать значение месяца на 1. А для этого нужно парсить входящую строку...


--------------------
Воспитывая детей по своему образу и подобию, родители почему-то надеются, что они будут лучше их.
PM MAIL   Вверх
skyboy
Дата 31.8.2008, 00:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

Репутация: 15
Всего: 260



ну, так используй второй вариант.
Цитата(Sunvas @  30.8.2008,  21:33 Найти цитируемый пост)
А для этого нужно парсить входящую строку

уже входящая строка какая-то. я-то думал, что мы говорим про SQL, который кто-то где-то генерирует...
PM MAIL   Вверх
Sunvas
Дата 31.8.2008, 01:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Соль и сахар
****


Профиль
Группа: Участник
Сообщений: 3388
Регистрация: 12.3.2006
Где: Тосно

Репутация: нет
Всего: 89



Цитата(skyboy @  31.8.2008,  00:53 Найти цитируемый пост)
уже входящая строка какая-то. я-то думал, что мы говорим про SQL, который кто-то где-то генерирует...

Ищу варианты, чтобы все сделать максимально производительно. Кстати о каком втором варианте Вы говорите?


--------------------
Воспитывая детей по своему образу и подобию, родители почему-то надеются, что они будут лучше их.
PM MAIL   Вверх
skyboy
Дата 31.8.2008, 12:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

Репутация: 15
Всего: 260



Цитата(Sunvas @  29.8.2008,  18:55 Найти цитируемый пост)
    
SELECT `date` FROM `table` WHERE MONTH(`date`)='5' AND YEAR(`date`)='2007'

второй вариант. кстати говоря, раз уж тут отдельно - месяц и год, то и в этом случае придется парсить строку.
но при большом количестве строк этот "единоразовый парсинг" будет незаметен на фоне выигрыша при использовании индекса по целочисленному полю(вариант "`date`>= '01-05-2007' AND `date`< '01-06-2007'") или при работе с числами вместо строк(WHERE MONTH(`date`)='5' AND YEAR(`date`)='2007').

PM MAIL   Вверх
Nigel
Дата 31.8.2008, 13:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


познаю мир
**


Профиль
Группа: Участник
Сообщений: 515
Регистрация: 20.11.2007

Репутация: нет
Всего: 19



Цитата(skyboy @ 30.8.2008,  21:38)
Nigel, вместо работы с целыми числами - преобразование в строку? кхм, к первоначальному вопросу про "запрос производительнее".

skyboy, и? При условии date<=/date>= все-равно будет идти сравнение строк. У автора дата же не в виде числа хранится
PM MAIL   Вверх
skyboy
Дата 31.8.2008, 13:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

Репутация: 15
Всего: 260



Цитата(Nigel @  31.8.2008,  12:42 Найти цитируемый пост)
При условии date<=/date>

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

Добавлено через 11 минут и 48 секунд
проводим эксперимент:
Код

CREATE TABLE `temp`(
`id`  INT auto_increment PRIMARY KEY,
`dt` datetime,
INDEX (`dt`)
);
INSERT INTO temp(`dt`)
SELECT now();

имеем одну запись. после чего выполняем запрос
Код

INSERT INTO `temp`(`dt`)
SELECT date_add(`dt`, INTERVAL (rand() - rand()) * 100 DAY)
FROM `temp`

несколько раз(я выполнил его 20 раз и получил, закономерно, 1048576 записей).
после чего выполняем:
Код

explain 
select *
from temp
where year(dt) = 2007

наблюдаем:
Цитата

"id"    "select_type"    "table"    "type"    "possible_keys"    "key"    "key_len"         "ref"    "rows"    "Extra"
"1"    "SIMPLE"    "temp"    "index"                 NULL    "dt"          "9"    NULL    "1049071"    "Using where; Using index"

т.е. индекс работает.
пробуем по-другому:
Код

explain 
select *
from temp
where dt> '05-10-2007'

картина меняется незначительно:
Цитата

"id"    "select_type"    "table"    "type"    "possible_keys"    "key"    "key_len"    "ref"       "rows"    "Extra"
"1"    "SIMPLE"         "temp"    "range"    "dt"                         "dt"         "9"          NULL     "524535"    "Using where; Using index"

индекс используется все равно.
пробуем вариант с like:
Код

explain 
select *
from temp
where dt like '%10-2007%'

К моему удивлению, индекс используется все равно:
Цитата

"id"    "select_type"    "table"    "type"    "possible_keys"    "key"    "key_len"    "ref"         "rows"    "Extra"
"1"    "SIMPLE"         "temp"    "index"                 NULL    "dt"         "9"           NULL    "1049071"    "Using where; Using index"

по всей видимости, оптимизатор умнее меня smile
вывод: по вопросам производительности лучше не искать совета со стороны, а самостоятельно провести полевые испытания.

Добавлено через 12 минут и 52 секунды
Цитата(Nigel @  31.8.2008,  12:42 Найти цитируемый пост)
У автора дата же не в виде числа хранится 

datetime - это число. то, что оно возвращается отформатированным в виде строки, не значит, что там и хранится строка.
PM MAIL   Вверх
Deniz
Дата 1.9.2008, 13:03 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1251
Регистрация: 16.10.2004
Где: Новый Уренгой

Репутация: 6
Всего: 44



Цитата(Nigel @  31.8.2008,  16:42 Найти цитируемый пост)
У автора дата же не в виде числа хранится
Тип date хранится как число дней(целый тип), прошедших с определенной даты. У разных СУБД эта стартовая дата может быть разная. Соответственно индекс по типу date сильно помогает в запросах.


--------------------
"Для того чтобы сделать шаг вперед, достаточно пинка сзади" (с)
PM ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Составление SQL-запросов | Следующая тема »


 




[ Время генерации скрипта: 0.0571 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.