Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Почему using temporary когда маленький cardinality / 7 сообщений из 7, страница 1 из 1
22.01.2015, 06:14:58
    #38860242
deblogger
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему using temporary когда маленький cardinality
Преамбула. 2 БД с двумя идентичными - favorite, и двумя одинаковыми таблицами - catalog. Делается запрос:

Код: sql
1.
2.
3.
4.
5.
6.
7.
select SQL_CALC_FOUND_ROWS 
`c`.*, 
`f`.`product_id` is not null as `fav` 
from `catalog` as `c` left join `favorite` as `f` 
on `f`.`product_id`=`c`.`id` and `f`.`user_id`=0 
order by `c`.`id` desc 
limit 0,32;



БД1 отвечает за микросекунды, БД2 думает 5 секунд. Explain показывает что БД2 не использует индекс, включает using temporary.

Амбула. В свойствах индексов найдено отличие: в таблице favorite БД1 cardinality=1, в идентичной таблице БД2 = 10. Ну потому что в БД2 просто 1 запись, а в БД2 - 10 штук. Через веб-интерфейс сайта добавил дюжину записей в избранное БД2 - using temporary сняло как рукой. Причем не важно какой там номер юзера, хоть 0 - как в запросе. БД2 стала отвечать за микросекунды.

Дамп структуры избранного:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
CREATE TABLE `favorite` (
 `id` int(12) unsigned NOT NULL AUTO_INCREMENT,
 `product_id` int(12) unsigned NOT NULL,
 `user_id` int(12) unsigned NOT NULL,
 `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
 PRIMARY KEY (`id`),
 KEY `product_id` (`product_id`)
) ENGINE=MyISAM AUTO_INCREMENT=36 DEFAULT CHARSET=utf8



Дамп каталога (общая часть двух таблиц, специфика вырезана)

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
CREATE TABLE `catalog` (
 `id` int(12) unsigned NOT NULL AUTO_INCREMENT,
 `pid` int(12) unsigned NOT NULL,
---
--- специфика поскипана
---
 PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=25084 DEFAULT CHARSET=utf8




Вопрос: это значит если юзеры удалят все избранное, или пока они туда не понакидают - БД будет зверски тормозить? Или как сделать чтобы и с пустой таблицей избранного запрос не качал из временной таблицы?

Заранее спасибо за полезные советы.
...
Рейтинг: 0 / 0
22.01.2015, 10:10:28
    #38860355
miksoft
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему using temporary когда маленький cardinality
Можно попытаться принудить MySQL всегда использовать индекс. См. Index Hint Syntax .

Я как-то налетал на схожую ситуацию, когда добавление индекса на крошечной таблице (меньше десятка записей) на порядок ускоряло запрос. Природу этого ускорения я тогда не выяснял, но есть ощущение, что это связано с тем, что в MyISAM нормально кэшируются только индексы, а содержимое таблицы - нет.


P.S.debloggerАмбула.Фабула.
...
Рейтинг: 0 / 0
22.01.2015, 17:22:01
    #38860942
deblogger
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему using temporary когда маленький cardinality
miksoft,

Да, когда написал припомнил что вроде есть форсированный режим, но искать не стал. Сейчас поищу, спасибо за совет.
...
Рейтинг: 0 / 0
22.01.2015, 17:28:07
    #38860949
deblogger
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему using temporary когда маленький cardinality
upd, теперь видать надо выкашивать индексы отдельно - удаление записей из избранного ситуацию не ухудшило чтобы проверить ваш совет. Отпишусь.
...
Рейтинг: 0 / 0
22.01.2015, 17:33:48
    #38860955
miksoft
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему using temporary когда маленький cardinality
Попутный совет - после таких операций как создание/удаление индекса и вставка большого количества записей делайте OPTIMIZE TABLE, а после удаления существенного количества записей делайте ANALYZE TABLE этой таблице. Иногда может изменить картину. Обычно в лучшую сторону.
...
Рейтинг: 0 / 0
22.01.2015, 18:09:59
    #38860998
deblogger
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему using temporary когда маленький cardinality
Удалил индекс, создал заново, запрос исправно начал лагать по 3 секунды. Попытки применить use index только потратили время. Заенфорсил force и стало все сладко да гладко. Вот так теперь выглядит.

Код: sql
1.
2.
3.
4.
5.
select SQL_CALC_FOUND_ROWS `c`.*, `f`.`product_id` is not null as `fav` 
from `catalog` as `c` 
left join `favorite` as `f` force index for join(`product_id`) 
on `f`.`product_id`=`c`.`id` and `f`.`user_id`=0 
order by `c`.`id` desc limit 0,36;



Про оптимизацию PMA подсказывает когда заглядываешь в нем в структуры время от времени. Но в этот раз я сперва сам все проверил, анализировал и оптимизировал.

PS А нормально так кушает этот SQL_CALC_FOUND_ROWS. Субъективно на фоне работы скрипта не заметно, а по числам - без него и лимита:

Showing rows 0 - 29 ( 14,057 total, Query took 0.0045 sec)

- с подсчетом и лимитом

Showing rows 0 - 35 ( 36 total, Query took 0.2184 sec)
...
Рейтинг: 0 / 0
22.01.2015, 18:13:28
    #38861002
miksoft
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему using temporary когда маленький cardinality
debloggerPS А нормально так кушает этот SQL_CALC_FOUND_ROWS.Естественно. При его использовании не срабатывает оптимизация ORDER BY + LIMIT и MySQL сортирует весь объем записей, а не только 36
...
Рейтинг: 0 / 0
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Почему using temporary когда маленький cardinality / 7 сообщений из 7, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]