SQLinfo.ru - Все о MySQL Webew.ru: теория и практика веб-технологий

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 19.08.2011 04:01:54

_Igor_
Участник
Зарегистрирован: 19.08.2011
Сообщений: 7

Нужна помощь с оптимизацией запроса выборки

Есть три таблицы: таблица товаров, таблица опций, и таблица связки товаров и опций, выглядит примерно так:

Таблица товаров: goods
(id, goods_name, goods_description, .....)

Таблица опций: option
(id, option_name)

Таблица связки товаров и опций: goods_option
(goods_id, option_id)

Для каждого товара может быть несколько опций. До некоторого времени, для поиска товара с определенными опциями использовался запрос с использованием INNER JOIN такого вида:
SELECT id,  goods_name, goods_description FROM goods
INNER JOIN goods_option AS op1 ON goods.id = op1.goods_id
INNER JOIN goods_option AS op2 ON goods.id = op2.goods_id
INNER JOIN goods_option AS op3 ON goods.id = op3.goods_id
......
WHERE
op1.option_id = 2 &&
op2.option_id = 15 &&
op3.option_id = 23 &&
......

По мере роста базы запросы начали подтормаживать, теперь в базе имеется ~70000 товаров, таблица связки товаров и опций ~100000 записей, если задавать поиск товаров хотя бы по 10 опциям, то 2-х ядерный сервак уходит в ступор от такого запроса.

Подскажите, плиз, можно ли как-то оптимизировать запрос?

Неактивен

 

#2 19.08.2011 04:13:11

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5847

Re: Нужна помощь с оптимизацией запроса выборки

SELECT id,  goods_name, goods_description FROM goods
INNER JOIN
(select goods_id from goods_option where option_id in (2,15,23) group by 1 having count(*)=3) opt
ON goods.id = opt.goods_id;

Неактивен

 

#3 19.08.2011 15:45:49

_Igor_
Участник
Зарегистрирован: 19.08.2011
Сообщений: 7

Re: Нужна помощь с оптимизацией запроса выборки

vasya, спасибо, помогло...
теперь сервак в ступор не уходит, время выполнения запроса ~0,65 сек

Решил посмотреть что показывает EXPLAIN, немного не понравилось что он не использует индекс в таблице goods_option даже если в запросе указать его использовать, получается что он проходит всю таблицу, а там на данный момент около миллиона записей.

Запрос:

SELECT COUNT(*) FROM goods
INNER JOIN
(select goods_id from goods_option where option_id in (51,15,12,2,11,29,9,6,20,21,19,24,26,27) group by 1 having count(*)=14) opt ON goods.id = opt.goods_id;


Вот что выдаёт EXPLAIN

id  select_type    table           type     possible_keys   key      key_len  ref                rows     Extra  
1   PRIMARY      <derived2>        ALL       NULL           NULL     NULL     NULL                733  
1   PRIMARY      goods             eq_ref    PRIMARY        PRIMARY   4       opt.goods_id          1     Using where
2   DERIVED      goods_option      ALL       option_id      NULL     NULL     NULL              909816    Using where; Using temporary; Using filesort
 



Подскажите, можно ли как-то ещё оптимизировать чтоб использовало индексы в таблице goods_optinon, а не пробегало всю таблицу?

Неактивен

 

#4 19.08.2011 16:10:50

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5847

Re: Нужна помощь с оптимизацией запроса выборки

1. Каким образом указываете использование индекса?
http://sqlinfo.ru/forum/viewtopic.php?id=231

2. Для избавления от "Using filesort" используйте order by null

3. Покажите show create table goods_option;

Неактивен

 

#5 20.08.2011 15:29:42

_Igor_
Участник
Зарегистрирован: 19.08.2011
Сообщений: 7

Re: Нужна помощь с оптимизацией запроса выборки

vasya написал:

1. Каким образом указываете использование индекса?
http://sqlinfo.ru/forum/viewtopic.php?id=231

сорри, забыл написать, когда указываю USE INDEX, оно не использует его, и результат EXPLAIN такой, как я привел выше. Если принудительно использовать индекс FORCE INDEX, тогда оно использует этот индекс, рядов пробегает в 2 раза меньше (413013, а не 909816), но время выполнения запроса ~4,5 сек


vasya написал:

2. Для избавления от "Using filesort" используйте order by null

сэнкс, такого не знал, буду в дальнешем применять


vasya написал:

3. Покажите show create table goods_option;

таблица была изначально такой:

CREATE TABLE IF NOT EXISTS `goods_option` (
  `goods_id` int(10) unsigned NOT NULL default '0',
  `option_id` int(10) unsigned NOT NULL default '0',
  KEY `goods_id` (`goods_id`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251;
 

но потом решил добавить индекс, поэкспериментировать, с целью уменьшить время запроса:
ALTER TABLE `goods_option` ADD INDEX `option_id` ( `option_id` )


почему-то казалось что наличие этого индекса сократит кол-во выбираемых рядов, как вообщем и получилось если его принудительно применять, но вот время выполнение говорит о том, что лучше без него )

Неактивен

 

#6 20.08.2011 16:54:53

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5847

Re: Нужна помощь с оптимизацией запроса выборки

_Igor_ написал:

Если принудительно использовать индекс FORCE INDEX, тогда оно использует этот индекс, рядов пробегает в 2 раза меньше (413013, а не 909816), но время выполнения запроса ~4,5 сек

В данном случае полный скан таблицы предпочтительней из-за последовательного чтения диска, поэтому оптимизатор совершенно прав не используя индекс.

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson