Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / MySQL [игнор отключен] [закрыт для гостей] / и снова фильтры / 8 сообщений из 8, страница 1 из 1
18.03.2015, 18:27:53
    #38908931
scion4581
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
и снова фильтры
Всем доброе время суток, требуется помощь по оптимизации запроса

В общем схема такова:

имеется таблица фильтров

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
CREATE TABLE IF NOT EXISTS `filters` (
`id` int(10) unsigned NOT NULL,
  `name` varchar(255) NOT NULL COMMENT 'название фильтра',
  `service_type_id` int(10) unsigned NOT NULL COMMENT 'категория',
  `user_id` int(10) unsigned NOT NULL COMMENT 'владелец фильтра',
  `add_date` datetime DEFAULT NULL COMMENT 'дата добавления',
  `status` enum('active','inactive') NOT NULL DEFAULT 'active' COMMENT 'статус фильтра'
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COMMENT='фильтры' AUTO_INCREMENT=22 ;



Каждый фильтр закреплен за пользователе (user_id). И у каждого фильтра есть join таблицы для множественного выбора

следующих характеристик: года выпуска, модели, регионы, услуги(по которым настраивается фильтр).

Реализация связей фильтров и этих таблиц с помощью объединяющих(join) таблиц так как должен быть множественный выбор по

каждому фильтру.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
CREATE TABLE IF NOT EXISTS `filter_vs_article` (
`id` int(10) unsigned NOT NULL,
  `filter_id` int(10) unsigned NOT NULL COMMENT 'фильтр',
  `service_article_id` int(10) unsigned NOT NULL COMMENT 'группа запчастей или услуг'
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COMMENT='фильтры - группы запчастей или услуг' AUTO_INCREMENT=376 ;

CREATE TABLE IF NOT EXISTS `filter_vs_made_year` (
`id` int(10) unsigned NOT NULL,
  `filter_id` int(10) unsigned NOT NULL,
  `made_year` year(4) NOT NULL COMMENT 'года выпуска'
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COMMENT='фильтры - года производства' AUTO_INCREMENT=457 ;

CREATE TABLE IF NOT EXISTS `filter_vs_model` (
`id` int(10) unsigned NOT NULL,
  `filter_id` int(10) unsigned NOT NULL COMMENT 'фильтер',
  `car_model_id` int(10) NOT NULL COMMENT 'модель'
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COMMENT='фильтры - модели' AUTO_INCREMENT=492 ;

CREATE TABLE IF NOT EXISTS `filter_vs_region` (
`id` int(10) unsigned NOT NULL,
  `filter_id` int(10) unsigned NOT NULL COMMENT 'фильтр',
  `region_id` int(10) unsigned NOT NULL COMMENT 'регион'
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COMMENT='фильтры - регионы' AUTO_INCREMENT=298 ;



Естественно есть таблицы с которыми приведенные выше таблицы связывают. Приводить их пока не буду потому что слишком длинным получится текст.

Так вот суть в том что нужно составить запрос который выбирает все фильтры по конкретному пользователю и показывает сгруппированные данные по которым фильтр настроен.

Например:

Фильтр1
Услуги: услуга1,услуга2,услуга3...
Года выпуска: 2000,2001,2004,2005...
Регионы: регион1, регион2, регион3...
Марки машин: Honda, BMW, Audi...
Модели машин: Accord, X5,A7

и так далее, список фильтров.

С марками фильтры связаны через модели.

Итого пишу следующий запрос:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
SELECT 
f.user_id,
f.add_date,
f.name,
GROUP_CONCAT(f_vs_year.made_year) years,
GROUP_CONCAT(distinct f_vs_article.service_article_id) articles,
GROUP_CONCAT(distinct mark.name) marks,
GROUP_CONCAT(distinct model.name) models

FROM filters f 

JOIN filter_vs_made_year f_vs_year ON f_vs_year.filter_id = f.id

JOIN filter_vs_model f_vs_model ON f_vs_model.filter_id = f.id
JOIN car_model model ON model.id_car_model = f_vs_model.car_model_id
JOIN car_mark mark ON mark.id_car_mark = model.id_car_mark

JOIN filter_vs_article f_vs_article ON f_vs_article.filter_id = f.id
JOIN service_articles s_articles ON s_article.id = f_vs_article.service_article_id

WHERE f.user_id = 36

GROUP BY f.id    ORDER BY f.add_date LIMIT 0,14



В итоге запрос занимает более 7 секунд и это почти пустая БД. Если убрать GROUP_CONCAT то индексы используются, но это GROUP_CONCAT да еще distinct тупо убивают всю производительность! :(

Буду благодарен за любые подсказки, пинки, тыканье носом и прочего по оптимизации такого запроса.
...
Рейтинг: 0 / 0
18.03.2015, 19:56:15
    #38909009
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
и снова фильтры
scion4581,

А план где ?
...
Рейтинг: 0 / 0
18.03.2015, 20:07:26
    #38909023
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
и снова фильтры
И с таким подходом будет сложно.

Либо надо будет хинты прописывать для каждого случая (типовых поисков), либо всё будет работать абы как.

Лучше бы было герерировать тексты запросов на основе фильтров, и выполнять их.
Это хотя бы какой-то выход на оптимизируемые запросы.
...
Рейтинг: 0 / 0
18.03.2015, 20:16:18
    #38909030
scion4581
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
и снова фильтры
Вот если без group_concat, индексы используются но не все
...
Рейтинг: 0 / 0
18.03.2015, 20:17:03
    #38909031
scion4581
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
и снова фильтры
но если добавить их то сразу становится null
...
Рейтинг: 0 / 0
18.03.2015, 20:19:24
    #38909034
scion4581
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
и снова фильтры
спасибо за ответ. пока приложение тестируется поэтому можно изменить и реализацию если что. Просто пугает что мало записей,

фильтров штук 15 и на каждый из них максимум по 20 записей в связывающей таблице а результат просто кошмарный. Как бы это

можно было бы пошустрее сделать. Спасибо за ответ
...
Рейтинг: 0 / 0
18.03.2015, 20:36:22
    #38909049
scion4581
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
и снова фильтры
Переписал запрос следующим образом, группируем каждую таблицу множественного выбора и соединяю по id фильтра и скорость

стала космический "Запрос занял 0.0091 сек." с 7 секунд то. хотя запрос ужасный вроде получился, стоит ли так делать
Код: 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.
SELECT 
f.id,
f.user_id,
f.add_date,
f.name,
years.years,
models.models,
models.marks,
regions.regions,
services.services

FROM filters f 

JOIN 

(SELECT 
 	GROUP_CONCAT(made_year) As years,
 	filter_id 
 	FROM filter_vs_made_year 
 	group by filter_id
) 
As years ON years.filter_id = f.id

JOIN 

(SELECT 
 	GROUP_CONCAT(model.name) As models,
    GROUP_CONCAT(mark.name) As marks,
 	filter_id 
 	FROM filter_vs_model f_vs_model 
    JOIN car_model model ON model.id_car_model = f_vs_model.car_model_id
    JOIN car_mark mark ON mark.id_car_mark = model.id_car_mark
 	group by filter_id
 )
As models ON models.filter_id = f.id

JOIN

 (SELECT GROUP_CONCAT(r.name) As regions,filter_id 
  FROM filter_vs_region f_vs_region
  JOIN regions r ON r.rid = f_vs_region.region_id
  
  group by filter_id
  )
As regions ON regions.filter_id = f.id

JOIN

 (SELECT GROUP_CONCAT(s.name_ru) As services,filter_id 
  FROM filter_vs_article f_vs_service
  JOIN service_article s ON s.id = f_vs_service.service_article_id
  
  group by filter_id
  )
As services ON services.filter_id = f.id


WHERE f.user_id = 36
...
Рейтинг: 0 / 0
19.03.2015, 18:48:46
    #38910370
scion4581
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
и снова фильтры
плохой ужасный запрос получился я так понял
...
Рейтинг: 0 / 0
Форумы / MySQL [игнор отключен] [закрыт для гостей] / и снова фильтры / 8 сообщений из 8, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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