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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Оптимизация запроса с count(*) 
:(
    Опции темы
sanich_
Дата 16.12.2014, 01:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Добрый день.
 
Уже голову сломал, пытаясь сделать запрос быстрее:

Запрос:
Код

(select id_categ id,categ name_,order_ categ_order,-1  rubrika_order,' ' count_ from categ) 
union all
(select r.id_rubrika id, r.rubrika,c.order_, r.order_,(select count(*) from object o where now()<o.date_del and o.id_rubrika=r.id_rubrika) as count_ from rubrika r ,categ c where r.id_categ=c.id_categ)
order by categ_order, rubrika_order


В таблице object 300000 записей
Потеря времени происходит в месте where now()<o.date_del 
Если убрать, сравнение now()<o.date_del то запрос летает
Пробовал сделать индекс по полю date_del, ничего не изменилось.

Как его можно оптимизировать?

Присоединённый файл ( Кол-во скачиваний: 5 )
Присоединённый файл  план_запроса.gif 15,40 Kb
PM MAIL   Вверх
_zorn_
Дата 16.12.2014, 03:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1076
Регистрация: 21.8.2007

Репутация: 2
Всего: 12



А если индекс по 2 полям сделать ?
(o.date_del and o.id_rubrika)
PM MAIL   Вверх
Akina
Дата 16.12.2014, 08:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 106
Всего: 454



Только поля наоборот, по (id_rubrika,date_del).


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
tzirechnoy
Дата 16.12.2014, 09:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1173
Регистрация: 30.1.2009

Репутация: 3
Всего: 16



1) вместо count -- SUM(IF(now()<o.date_del, 1, 0)
2) Если тупит вызов now() -- то [во-первых, перейти на 64-бит линукс, в котором это не требует сисколла через прерывания] сохранить now() до формирования запроса и поставить его как параметр.
PM MAIL   Вверх
Akina
Дата 16.12.2014, 10:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 106
Всего: 454



Цитата(tzirechnoy @  16.12.2014,  10:57 Найти цитируемый пост)
вместо count -- SUM(IF(now()<o.date_del, 1, 0)

А вот это - фуллскан однозначно. И никакой индекс не спасёт - в лучшем случае это будет фуллскан индекса.

Цитата(tzirechnoy @  16.12.2014,  10:57 Найти цитируемый пост)
Если тупит вызов now() 

Он не может тупить в принципе. Ибо выполняется ровно один раз, причём до начала выполнения самого запроса.


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
sanich_
Дата 16.12.2014, 14:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата(tzirechnoy @ 16.12.2014,  09:57)
1) вместо count -- SUM(IF(now()<o.date_del, 1, 0)
2) Если тупит вызов now() -- то [во-первых, перейти на 64-бит линукс, в котором это не требует сисколла через прерывания] сохранить now() до формирования запроса и поставить его как параметр.

Попробовал 
Код

SUM(IF(now()<o.date_del, 1, 0)


Быстрее не стало...

Добавлено @ 14:52
Цитата(Akina @ 16.12.2014,  08:51)
Только поля наоборот, по (id_rubrika,date_del).

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


Это сообщение отредактировал(а) sanich_ - 16.12.2014, 14:54

Присоединённый файл ( Кол-во скачиваний: 5 )
Присоединённый файл  план.gif 15,49 Kb
PM MAIL   Вверх
Akina
Дата 16.12.2014, 15:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 106
Всего: 454



Цитата(sanich_ @  16.12.2014,  15:50 Найти цитируемый пост)
Индекс по двум полям добавил

Покажи итоговую SHOW CREATE TABLE object 

Цитата(sanich_ @  16.12.2014,  15:50 Найти цитируемый пост)
что еще можно придумать?

А не то же самое будет
Код

select
  r.id_rubrika id
, r.rubrika
, c.order_
, r.order_
, count(o.id_rubrika) count_ 
from rubrika r 
inner join categ c on r.id_categ=c.id_categ
left join object o on o.id_rubrika=r.id_rubrika and now()<o.date_del

? навскидку нарисовал... проверь. 

А исходный запрос с коррелирующим подзапросом я не вижу как ещё разогнать...


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
sanich_
Дата 16.12.2014, 15:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата(Akina @ 16.12.2014,  15:32)
Цитата(sanich_ @  16.12.2014,  15:50 Найти цитируемый пост)
Индекс по двум полям добавил

Покажи итоговую SHOW CREATE TABLE object 

Цитата(sanich_ @  16.12.2014,  15:50 Найти цитируемый пост)
что еще можно придумать?

А не то же самое будет
Код

select
  r.id_rubrika id
, r.rubrika
, c.order_
, r.order_
, count(o.id_rubrika) count_ 
from rubrika r 
inner join categ c on r.id_categ=c.id_categ
left join object o on o.id_rubrika=r.id_rubrika and now()<o.date_del

? навскидку нарисовал... проверь. 

А исходный запрос с коррелирующим подзапросом я не вижу как ещё разогнать...

Код

CREATE TABLE `object` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `title` varchar(200) NOT NULL,
  `id_rubrika` int(11) default NULL,
  `id_razdel` smallint(5) unsigned default NULL,
  `id_gorod` smallint(5) default NULL,
  `count_view` int(11) NOT NULL default '0',
  `address` tinytext,
  `description` text,
  `contact` tinytext,
  `phone` tinytext,
  `email` tinytext,
  `url` tinytext,
  `date_` datetime default NULL,
  `term` smallint(6) default NULL,
  `date_del` datetime default NULL,
  `count_show` int(11) default '0',
  `domain` tinytext,
  `ip` varchar(15) default NULL,
  `blok` tinyint(4) default '0',
  `pass` varchar(20) default NULL,
  `count_image` tinyint(4) default '0',
  `is_vip` tinyint(4) default '0',
  `vip_count_month` smallint(4) default '0',
  `date_vip_pay` datetime default NULL,
  `date_vip_end` datetime default NULL,
  `notify_user_on_delete` enum('yes','no') NOT NULL default 'no',
  `price` double default '0',
  PRIMARY KEY  (`id`),
  KEY `id_rubrika_ind` (`id_rubrika`),
  KEY `id_razdel_ind` (`id_razdel`),
  KEY `blok_ind` (`blok`),
  KEY `is_vip_ind` (`is_vip`),
  KEY `id_gorod_ind` (`id_gorod`),
  KEY `date_del` (`date_del`),
  KEY `id_razdel` (`id_razdel`,`date_del`),
  FULLTEXT KEY `description_ind` (`description`,`title`),
  FULLTEXT KEY `title_ind` (`title`)
) ENGINE=MyISAM AUTO_INCREMENT=381479 DEFAULT CHARSET=cp1251



Запрос:
Код

select
  r.id_rubrika id
, r.rubrika
, c.order_
, r.order_
, count(o.id_rubrika) count_ 
from rubrika r 
inner join categ c on r.id_categ=c.id_categ
left join object o on o.id_rubrika=r.id_rubrika and now()<o.date_del
group by id


Выполняется чуть дольше....
PM MAIL   Вверх
Akina
Дата 16.12.2014, 16:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 106
Всего: 454



Цитата(sanich_ @  16.12.2014,  16:42 Найти цитируемый пост)
Запрос: [skipped] Выполняется чуть дольше.... 

Это неважно. Главное - я нигде логику не переврал?
Если всё нормально - покажи его explain.



--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
tzirechnoy
Дата 16.12.2014, 21:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1173
Регистрация: 30.1.2009

Репутация: 3
Всего: 16



Цитата
Быстрее не стало...


Ну, я там не указал, но now()<o.date_del надо было убрать.
Что-то когда писал -- думал, что это какбы очевидно (да и @Akina это было очевидно).
PM MAIL   Вверх
_zorn_
Дата 17.12.2014, 03:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1076
Регистрация: 21.8.2007

Репутация: 2
Всего: 12



Цитата(sanich_ @  16.12.2014,  21:50 Найти цитируемый пост)
Индекс по двум полям добавил, быстрее не стало

Что то я не вижу такого индекса. Вижу только
Код
KEY `id_rubrika_ind` (`id_rubrika`)

Код
KEY `date_del` (`date_del`)

и
Код
KEY `id_razdel` (`id_razdel`,`date_del`)

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | MySQL | Следующая тема »


 




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


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

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