Оптимизация запроса

LONGMAN

Dark Side of the Moon..
Wicked
Спасибо большое. Интересный очен подход. А говорили что вложенные запросы это зло. Видима тут тоже it depends
 

Wicked

Новичок
да, тут тоже... вложенные запросы разные бывают, но в mysql они почти все вредные, ибо сделаны через одно место :)

а можно получившийся explain посмотреть?
 

LONGMAN

Dark Side of the Moon..
Wicked
конечно.
Запрос:
[sql]
SELECT `p` . *
FROM `shoppingcart_products` AS `p`
INNER JOIN (
SELECT `id`
FROM `shoppingcart_products`
ORDER BY `date` DESC
LIMIT 10
) AS `p2` ON ( `p`.`id` = `p2`.`id` )
LEFT JOIN `shoppingcart_products_data` AS `d` ON `p`.`id` = `d`.`itemid`
LEFT JOIN `shoppingcart_products_categories` AS `pc` ON `pc`.`pid` = `p`.`id`
LEFT JOIN `shoppingcart_categories` AS `cc` ON `cc`.`id` = `pc`.`cid`
LEFT JOIN `shoppingcart_currency` AS `cur` ON `cur`.`id` = `p`.`currency`
LEFT JOIN `shoppingcart_manufacturers_data` AS `m` ON `m`.`itemid` = `p`.`manufacturer`
LEFT JOIN `shoppingcart_users` AS `u` ON `u`.`id` = `p`.`added_by`
GROUP BY `p`.`id`
[/sql]
Explain:
Код:
id 	select_type 	table 	type 	possible_keys 	key 	key_len 	ref 	rows 	Extra
1 	PRIMARY 	<derived2> 	ALL 	NULL 	NULL 	NULL 	NULL 	10 	Using temporary; Using filesort
1 	PRIMARY 	p 	eq_ref 	PRIMARY 	PRIMARY 	4 	p2.id 	1 	 
1 	PRIMARY 	d 	ref 	itemid 	itemid 	4 	mydb.p.id 	2 	Using index
1 	PRIMARY 	pc 	ref 	PRIMARY 	PRIMARY 	4 	mydb.p.id 	2 	Using index
1 	PRIMARY 	cc 	eq_ref 	PRIMARY 	PRIMARY 	4 	mydb.pc.cid 	1 	Using index
1 	PRIMARY 	cur 	eq_ref 	PRIMARY 	PRIMARY 	4 	mydb.p.currency 	1 	Using index
1 	PRIMARY 	m 	ref 	itemid 	itemid 	4 	mydb.p.manufacturer 	1 	Using index
1 	PRIMARY 	u 	eq_ref 	PRIMARY 	PRIMARY 	4 	mydb.p.added_by 	1 	Using index
2 	DERIVED 	elva_wsshoppingcart_products 	index 	NULL 	date 	8 	NULL 	4655
-~{}~ 05.08.10 12:28:

Не смотря на опять печальный explain, запрос выполняется гораздо быстрее.
Первый вариант: 1.3057 sec
Второй вариант: 0.0108 sec
Обе выполнил с ключом SQL_NO_CACHE
 

Wicked

Новичок
ну формально да, он не очень :) просто записей теперь обрабатывается не так много.

а еще попробуй заменить на group by p2.id, filesort не пропадет?
 

Gas

может по одной?
LONGMAN
Вполне нормальный explain, просто нужно понимать ход выполнения, type=ALL при джойне derived запроса будет всегда, потому что данные полученные таким запросом находятся в памяти, нет там никаких индексов. Но с учётом того, что именно к этим данным происходит привязка других таблиц, то какой type совершенно не важно. Using temporary; Using filesort - для нескольких десятков записей совершенно не страшно.

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

...вложенные запросы разные бывают, но в mysql они почти все вредные, ибо сделаны через одно место
может подзапросы? а то вложенные запросы и подзапросы суть разные вещи. Кстати, в mysql 5.4 они ускорили подзапросы, только не понятно, касается это correlated subquery или нет.
Wicked, ты скорее всего это всё знаешь, но вдруг кому тоже будет интересно :)

-~{}~ 05.08.10 11:26:

а еще попробуй заменить на group by p2.id, filesort не пропадет?
по идее не должен, данные из вложенного запроса без индексов, мне кажется в любом случае filesort будет, хотя он и не страшен на таком количестве записей.
 

Wicked

Новичок
не, на 5.4 я еще не смотрел, ибо его один фиг нигде нету :) но щас почитаю, угу
 

Gas

может по одной?
я смотрю 5.4 версию они уже спрятали, 5.5 только есть, надеюсь все оптимизации с 5.4 туда перенесли.
 

LONGMAN

Dark Side of the Moon..
Wicked
Нет, не пропал. Думаешь ещё нуждается этот запрос оптимизации? Может стоит изменить архитектуру бд..
 

LONGMAN

Dark Side of the Moon..
Gas
Спасибо за пояснений. О таких тонкостях MySQL в мануалах не прочтёшь :)

-~{}~ 05.08.10 13:48:

Wicked
Абсолютно устраивает :)

-~{}~ 05.08.10 13:55:

Еще есть такой запрос:
[sql]
SELECT `p`.*
FROM `shoppingcart_products` AS p
LEFT JOIN `shoppingcart_products_data` AS `d`
ON `p`.`id`=`d`.`itemid`
LEFT JOIN `shoppingcart_products_categories` AS `pc`
ON `p`.`id`=`pc`.`pid`
LEFT JOIN `shoppingcart_categories` AS `cc`
ON `cc`.`id` = `pc`.`cid`
LEFT JOIN `shoppingcart_currency` AS `cur`
ON `cur`.`id` = `p`.`currency`
WHERE ( (`cc`.`left_key`>=2
AND `cc`.`right_key`<=217) )
AND (`p`.`published`="1")
AND (`p`.`id`!="0")
AND (`p`.`smallimg` != "")
AND (`d`.`lang` = "1")
GROUP BY `p`.`id`
ORDER BY `p`.`date` DESC
LIMIT 3
[/sql]
Explain:
Код:
id 	select_type 	table 	type 	possible_keys 	key 	key_len 	ref 	rows 	Extra
1 	SIMPLE 	d 	ref 	lang,itemid 	lang 	4 	const 	2122 	Using where; Using temporary; Using filesort
1 	SIMPLE 	p 	eq_ref 	PRIMARY,publish_idx,smallimg 	PRIMARY 	4 	mydb.d.itemid 	1 	Using where
1 	SIMPLE 	cur 	eq_ref 	PRIMARY 	PRIMARY 	4 	mydb.p.currency 	1 	Using index
1 	SIMPLE 	pc 	ref 	PRIMARY 	PRIMARY 	4 	mydb.p.id 	2 	Using where; Using index
1 	SIMPLE 	cc 	eq_ref 	PRIMARY,idx_lft_rgt 	PRIMARY 	4 	mydb.pc.cid 	1 	Using where
Запрос выполняется > 1.0 sec
 

Gas

может по одной?
Попробуй тоже с вложенным запросом по таблице shoppingcart_products
 

LONGMAN

Dark Side of the Moon..
Gas
Время сократилась до 0.2 sec. Гуд :) Но мне интересно как выбрать все продукты с определённой категории и ниже, при nested sets. Ведь так как я делаю? Узнать с начала left_key и right_key категории и потом join категории при выборке с products
 

Wicked

Новичок
откуда такая любовь к left join?

а этот я бы разбил на такие:
1) выбор left, right верхней категории
2) выбор вложенных категорий по left, right, но только не так, как у тебя, а по условию
`cc`.`left_key` >= 2 AND `cc`.`left_key` <= 217
причем нужно иметь индекс по left_key
3) дурацкий запрос почти без использования индексов: from pc inner join p on (... = ...) where pc.cid in (...) and `p`.`published` = "1" and `p`.`id` != "0" and `p`.`smallimg` != "" order by `date` desc limit 3;
4) либо довыбираем все остальное, либо исползуем 3й запрос в качестве подзапроса, предоставляющего 3 id-шника продуктов. Соотв-но из внешнего запроса у нас уходит все, что касается определения продуктов, категорий, сортировки, лимита.
 

LONGMAN

Dark Side of the Moon..
Wicked
А выражение IN (...) не будет тормозить, если количество значении в нём будет болше 100?
 

Wicked

Новичок
LONGMAN
не должен

кстати, какой смысл в выражении `p`.`id` != "0" ?
 

LONGMAN

Dark Side of the Moon..
weregod
Как сравнить один запрос и три запроса? К тому же если тот один запрос выполняется за 0.1-0.2 sec

-~{}~ 07.08.10 13:30:

Wicked
Никакой. Я вообше убрал его. Этот магазин я написал давно, и не очен то хорошо, если честно :) И вот приходится оптимизировать
 

weregod

unserializer
LONGMAN
набить БД данными и померить, с какой скоростью выполняются запросы (1 против трёх)
 
Сверху