Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / Помогите оптимизировать запрос в базу MySQL / 8 сообщений из 8, страница 1 из 1
09.04.2014, 03:49
    #38609210
Serious2008
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите оптимизировать запрос в базу MySQL
Здравствуйте. Есть один большой запрос, под спойлером. Изначально он был вот таким извращением http://pastebin.com/ukL7Hx5N
В итоге у меня получилось то что под спойлером, из того что я сам не смог додумать, это как сократить часть с mpar, т.е. этот большой селект, который формирует "mpar.mparams"

Сам я крайне плохо знаю все фишки для работы с SQL-ем, по этой причине вынужден просить помощи. Помогите оптимизировать эту большую часть, т.к. выборка со скоростью 180 секунд, крайне негативно сказывается на сайте, без этот mpars выборка проходит за 0.00022 секунды.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
	select g.id, pr.price, ifnull(pic1.fname, pic2.fname) as pic,  g.name as name, p.name as parname,
		ifnull(g.text_begin, p.text_begin) as descript, rg.yname,
		rg.artik as vendorid,
		mpar.mparams,
                pp.add as pricedeliv,
				concat(fv3.tid, '_', case when fv1.flt_id=fv2.flt_id then fv1.tid else fv2.tid end, 
'/', case when ifnull(g.tid,'')!='' then g.tid else g.id end) as tflt,
		ifnull(fv1.txt_value, fv2.txt_value) as brand, ifnull(fv1.text2, fv2.text2) as country,
		fv3.id as cat,
		ifnull(fv1.ym, fv2.ym) as brand2,
		fv3.txt_value as categ
from 
goods g 

left join goods p on p.id = g.parent

		left join (pictures pic1,pictures_goods pg1) on g.id=pg1.good_id and pic1.type='foto' and pic1.id=pg1.pic_id
		left join (pictures pic2,pictures_goods pg2) on g.parent=pg2.good_id and pic2.type='foto' and pic2.id=pg2.pic_id
		join (price pr) on g.id=pr.good_id and pr.type='out' and pr.coun=0  and pr.price>1 
		left join (remains_goods rg) on g.id=rg.good_id 
		left join (goods_filters gf1) on g.id=gf1.good_id and gf1.flt_id=3
		left join (filters_values fv1) on gf1.value=fv1.id 
		left join (goods_filters gf2) on p.id=gf2.good_id and gf2.flt_id=3
		left join (filters_values fv2) on gf2.value=fv2.id
		
		left join (goods_filters gf3) on p.id=gf3.good_id and gf3.flt_id=1
		left join (filters_values fv3) on gf3.value=fv3.id 
		left join (price_params pp) on pp.type=fv3.id and pp.brand=ifnull(fv1.id, fv2.id)
								 and (pr.price between pp.mini and pp.maxi)
		,
			(select vals.gid id, group_concat( distinct case when (vals.flt_id is null or vals.srt=-1) then null else
			concat(vals.name, '=', ifnull(vals.int_value, ifnull(vals.ym, vals.txt_value)),'||' , vals.ed, '||', digits)
			  end  order by vals.srt separator ';' ) mparams
				 from (
				  select g.id gid,
				  group_concat(distinct ifnull(fv.txt_value,fv2.txt_value) order by c.srt separator ', ') txt_value,
				  group_concat(distinct ifnull(fv.text2,fv2.text2) order by fv.srt,fv2.srt separator ' ') text2,
				  group_concat(distinct ifnull(fv.ym,fv2.ym) order by fv.srt,fv2.srt separator ' ') ym,
				  
				 ifnull(gf.int_value, gf2.int_value) int_value,
				 ifnull(gf.flt_id, gf2.flt_id) flt_id,
				c.tid, c.name, f.ed, c.srt, c.digits
				from
				(goods g, cat_filters c, filters f)
				left join goods_filters gf  on gf.good_id=g.id and c.flt_id=gf.flt_id
				left join filters_values fv on fv.id=gf.value
				left join goods_filters gf2  on gf2.good_id=g.parent and c.flt_id=gf2.flt_id
				left join filters_values fv2 on fv2.id=gf2.value
				where
				g.parent is not null
				and c.type =7
				and c.mflt in(select value from goods_filters gff where g.parent=gff.good_id and gff.flt_id=1 )
				and c.flt_id=f.id
				and c.`srt`>-1
				and case when f.type=5 then fv.tid=substring_index(c.tid,'/',-1) else 1=1 end
				and g.id in(select good_id from remains where num>2)
				group by g.id, c.tid,case when f.type=5 then gf.value else '' end

				 ) vals
				group by vals.gid
				) mpar
 
		WHERE

 g.active=1
 and p.active=1

 and g.parent in(select good_id from goods_filters gf, filters_values fv where fv.flt_id=1 and ifnull(fv.ym,'')!='' and fv.id=gf.value)
 and g.id in(select good_id from remains_goods)
 
 group by g.id

...
Рейтинг: 0 / 0
09.04.2014, 06:51
    #38609229
tanglir
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите оптимизировать запрос в базу MySQL
Serious2008выборка со скоростью 180 секунд, крайне негативно сказывается на сайте, без этот mpars выборка проходит за 0.00022 секунды.Вырезаете подзапрос "mpar", ставите перед ним explain, выполняете, результат - сюда (лучше в теге fixed)
Но вообще-то запрос сам по себе бредовый. Если его конкретно подсократить, то получится
Код: sql
1.
2.
3.
4.
select g.id, mpar.mparams
from g
 ,mparams /*а судя по "group by vals.gid" унутре этого запроса, запись там будет не одна*/
group by g.id

Чувствуете дурь?
А вот это
Код: sql
1.
case when f.type=5 then fv.tid=substring_index(c.tid,'/',-1) else 1=1 end

, похоже, вообще собиралось автоматическим кодописцем...
PS. А тему надо бы, наверное, перенести в соотв. подфорум.
...
Рейтинг: 0 / 0
09.04.2014, 12:08
    #38609600
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите оптимизировать запрос в базу MySQL
Serious2008,

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

Ну и в заключении -- тут надо разбираться в постановке задачи, в твоей БД, и в запросе.
Очевидно, что у тебя тут много вложенных group by по разным наборам полей, надо ли это -- не понятно, и можно ли это исправить -- тоже.

Так что скорее всего тебе придётся попотеть самому.
Или обратиться к профессионалам.
...
Рейтинг: 0 / 0
09.04.2014, 12:10
    #38609601
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите оптимизировать запрос в базу MySQL
Serious2008,

Думаю, запрос лучше заново наново переписывать, постигая его суть.
...
Рейтинг: 0 / 0
09.04.2014, 15:27
    #38610056
Serious2008
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите оптимизировать запрос в базу MySQL
Т.к. вставляя в FIXED Результат с EXPLAIN получался кривоват, я сделал скрин.


Я наконец-то понял принцип работы этой части mpar. Она собирает все параметры.
Принцип у него вот такой.
Из таблицы cat_filters выбираются значения вот с таким принципом
Код: sql
1.
WHERE  `mflt` = fv3.id AND  `type` =7 AND c.`srt`>-1


Далее, я получаю, примерно такую таблицу
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
id	flt_id	mflt	name	                        srt	tid	        digits	type
798	2 	2	Установка	                1	subtypes	0	7
1040	2 	2	Тип каминной вытяжки	3	kamint	1	7
1043	2 	2	Тип встраивания	        4	intype	2	7
1051	2764 	2	Цвет	                        16	color	        0	7
1052	2764 	2	Немаркая поверхность	17	nemark	1	7
1045	2765 	2	Тип управления	        10	uprav1	0	7
1046	2765 	2	Элементы управления	11	uprav2	1	7
1053	2943 	2	Ширина|см                 18	size/width  -10	7

Теперь дальше из таблицы goods_filters нужно выбрать очень хитрым образом данные.
Нужно выбрать в соответствии с flt_id все данные.
Т.е. условие что-то вроде
Код: sql
1.
WHERE goods_filters.flt_id = cat_filters.flt_id AND (goods_filters.good_id = g.id OR goods_filters.good_id = p.id)

но тут же опять, если есть в этой таблице параметр для g.id, то значение для p.id нужно игнорировать.

Т.е. получаем для значения g.id = 3074 и p.id=2074 и cat_filters.flt_id =2943
Вот такую вещь
Код: plaintext
1.
2.
id	        good_id	flt_id	value	        int_value	text_value	multi
821364	3074   	2943	27328 	900		                NULL

Теперь уже из таблицы filters_values нужно получить значение по столбцу value.
Получаем вот такое.
Код: plaintext
1.
2.
id	   flt_id	txt_value	int_value	srt	text2	active	tid	ym
27328   2943 	Ширина	0	       1	Ш	1	        width	NULL
И ещё из таблицы filters, нужно выбрать с подобным уловием WHERE id= cat_filters.flt_id
И получить вот такую вещь.
Код: plaintext
1.
2.
id	type	name	      descript	                ed	onlyif	descript2	descript_big
2943	5 	outsizes   Габаритные размеры	мм	NULL	NULL	        NULL
И в итоге нужно из всех этих таблиц получить вот такую вещь
Ширина|см=900||мм||-10
Если описывать то получается вот такая вещь.

Код: sql
1.
"cat_filters.name"+"="+IFNULL(goods_filter.int_value, IFNULL(filters_value.ym,filters_value.txt_value))+"||"+filters.ed+"||"+cat_filters.digits


И если это не последний параметр то добавляем ещё в конце ";"

Итог выполнения для одного товара
Установка=каминная|пристеннаяс**а0;Режим работы=отвод / циркуляцияс**а0;Тип каминной вытяжки=каминная|пристеннаяс**а1;Тип встраивания=каминная|пристеннаяс**а2;Тип управления=механическое|ползунковоес**а0;Элементы управления=механическое|ползунковоес**а1;Тип освещения=лампа накаливанияс**а0;Количество ламп освещения=2|25 ||||0;Мощность каждой лампы|Вт=2|25 ||||1;Цвет=серебристыйс**а0;Немаркая поверхность=серебристыйс**а1;Ширина|см=900||мм||-10

Вот нужно чтобы собралась вот такая строка. Теперь у меня возникли сомнения, что изначальный вариант плохой.
Я в SQL очень плох, так что я не знаю как оптимальней всего собирать эти данные :-(

P.S. Перепроектировать всё не вариант, т.к. очень много вещей завязано на эту базу, и проектировал её не я. И изначальный запрос, тоже не моих рук дело. Мне дали базу, и сказали, что выбираются не все товары. Начал ковырять и нарвался на этот запрос, потом обнаружил лишнее условие, которое много чего резало, что не должно быть обрезано.

tanglir PS. А тему надо бы, наверное, перенести в соотв. подфорум.
Я не нашёл более подходящий подфорум :-(
...
Рейтинг: 0 / 0
09.04.2014, 20:44
    #38610469
Serious2008
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите оптимизировать запрос в базу MySQL
Попытался сам для начала составить просто запрос с одним товаром, без подстановки всех данных, чтобы в итоге сделать на JOIN-ах.
Получилась вот такая вещь.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
SELECT
group_concat(distinct
 concat(c.name, '=', ifnull(gf1.int_value, IFNULL(gf2.int_value, IFNULL(fv1.ym, IFNULL(fv2.ym, IFNULL(fv1.txt_value, fv2.txt_value)))))
,'||' , f.ed, '||', c.digits)
                           order by c.srt separator ';' ) mparams
 FROM cat_filters c
LEFT JOIN goods_filters gf1 ON c.flt_id = gf1 .flt_id  AND gf1.good_id=3074
LEFT JOIN goods_filters gf2 ON c.flt_id = gf2  .flt_id  AND gf2 .good_id=2074
LEFT JOIN filters_values fv1 ON gf1.value = fv1.id 
LEFT JOIN filters_values fv2 ON gf2.value = fv2.id 
LEFT JOIN filters f ON c.flt_id = f.id 
 WHERE c.mflt = 2 AND  c.type =7 AND c.srt>-1
GROUP BY c.mflt ORDER BY `c`.`srt` ASC


Но результат не очень, он компонует все полностью и из 2074 и 3074
Установка=||||0;Установка=каминная|пристеннаяс**а0;Режим работы=отвод / циркуляцияс**а0;Тип каминной вытяжки=||||1;
Тип каминной вытяжки=каминная|пристеннаяс**а1;Тип встраивания=||||2;Тип встраивания=каминная|пристеннаяс**а2;
Производительность|куб.м/ч=1260||м<sup>3</sup>/ч||0;Количество скоростей=4с**а0;Тип управления=электронноех..во0;
Элементы управления=электронноех..во1;Тип освещения=галогенная лампас**а0;Количество ламп освещения=2|40 ||||0;
Мощность каждой лампы|Вт=2|40 ||||1;Таймер=естьс**а0;Цвет=серебристыйс**а0;Немаркая поверхность=серебристыйс**а1;
Ширина|см=900||мм||-10;Глубина/см=900||мм||-10
...
Рейтинг: 0 / 0
10.04.2014, 10:57
    #38610856
tanglir
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите оптимизировать запрос в базу MySQL
Serious2008Далее, я получаю, примерно такую таблицу
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
id	flt_id	mflt	name	                        srt	tid	        digits	type
798	2 	2	Установка	                1	subtypes	0	7
1040	2 	2	Тип каминной вытяжки	3	kamint	1	7
1043	2 	2	Тип встраивания	        4	intype	2	7
1051	2764 	2	Цвет	                        16	color	        0	7
1052	2764 	2	Немаркая поверхность	17	nemark	1	7
1045	2765 	2	Тип управления	        10	uprav1	0	7
1046	2765 	2	Элементы управления	11	uprav2	1	7
1053	2943 	2	Ширина|см                 18	size/width  -10	7
Теперь дальше из таблицы goods_filters нужно выбрать очень хитрым образом данные.
Нужно выбрать в соответствии с flt_id все данные.
Т.е. условие что-то вроде
Код: sql
1.
WHERE goods_filters.flt_id = cat_filters.flt_id AND (goods_filters.good_id = g.id OR goods_filters.good_id = p.id)


но тут же опять, если есть в этой таблице параметр для g.id, то значение для p.id нужно игнорировать.

Т.е. получаем для значения g.id = 3074 и p.id=2074 и cat_filters.flt_id =2943И вот тут я перестал что-либо понимать. Откуда 2074? и что это за таблица "p"?
Serious2008Я не нашёл более подходящий подфорум :-(название этого подфорума - в заголовке темы :)

PS. Судя по эксплейну, надо как минимум избавиться от подзапроса к таблицу remains. А лучше от обоих.
PPS. если FIXED не работает как надо, то есть ещё CSV.
...
Рейтинг: 0 / 0
10.04.2014, 11:15
    #38610883
Serious2008
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите оптимизировать запрос в базу MySQL
tanglirИ вот тут я перестал что-либо понимать. Откуда 2074? и что это за таблица "p"?

Код: sql
1.
2.
3.
4.
from 
goods g 

left join goods p on p.id = g.parent


Это отсылка к основному запросу.
g.id = 3074 - это id одного товара, а 2074 это его parent
Это реальные данные я подставил, чтобы данные в таблицах получались
...
Рейтинг: 0 / 0
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / Помогите оптимизировать запрос в базу MySQL / 8 сообщений из 8, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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