Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Оптимизация запроса (выборка 1 значения из 4 таблиц) / 3 сообщений из 3, страница 1 из 1
07.10.2015, 18:22:14
    #39071119
grecha10
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация запроса (выборка 1 значения из 4 таблиц)
Здравствуйте!

Есть мультирегиональный агрегатор товаров различных продавцов.
В БД есть таблица регионов (hdbk_regions), таблица рубрик (hdbk_rubrics), таблица товаров (catalog) и таблица связей фирма-регион (firm_region).

Таблица рубрик и таблица регионов - деревья значений (path имеет вид 1/123/458/..)

Каждому товару из catalog соответствует строго одна рубрика из hdbk_rubrics, строго конечная в ветке (без детей).
Каждому товару из catalog соответствует строго один idFirm (идентификатор продавца, сама таблица продавцов к задаче не относится).

Каждому идентификатору idFirm соответствует одна или несколько строк в firm_region.
Каждый продавцу(idFirm) может соответствовать firm_region.idRegion как конечный в ветке (без детей), так и промежуточный (с детьми).

Каждому идентификатору idRegion соответствует строго одна строка hdbk_regions.

Не в каждом регионе есть товары во всех рубриках.

Задача: по произвольной паре переменных (конечных или промежуточных в дереве) $idRegion, $idRubric определить, есть ли в БД товары для этой пары.

Структура таблиц:

hdbk_regions id, parentid, lev, path
hdbk_rubrics id, parentid, lev, path
catalog id, idFirm, idRegion
firm_region id, idFirm, idRegion

Мое решение.

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

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
            SELECT c.id
                    FROM catalog c
                    INNER JOIN hdbk_rubrics rub ON c.idRubric=rub.id
                    INNER JOIN firm_region f2r ON f2r.idFirm=c.idFirm
                    INNER JOIN hdbk_regions reg ON reg.id=f2r.idRegion
                    WHERE (rub.path LIKE (SELECT CONCAT(path,'/%') FROM hdbk_rubrics WHERE id = '$idRubric') OR rub.id='$idRubric')
                        AND (reg.path LIKE (SELECT CONCAT(path,'/%') FROM hdbk_regions WHERE id = '$idRegion') OR reg.id='$idRegion')
                    LIMIT 1



Работает правильно, но мне не удалось подобрать такую комбинацию индексов, что бы не было полного перебора таблиц catalog или firm_region. А эти таблицы увеличиваются, и ясно что это не приемлемо. Ну и Limit здесь как бы не лимит, в том смысле что запрос выдает конечно единственное значение, но по ощущениям перебор не останавливается после первого найденного результата, а продолжается.

Как решить такую задачу наиболее правильно, кто знает?? Может быть есть какой то лучший алгоритм, чем простой join таблиц?

ЗЫ Если кто то захочет не просто ответить, а поэкспериментировать на реальных данных, дамп БД выложил сюда http://my-files.ru/p6ueh4 (400 Кб., zip).
...
Рейтинг: 0 / 0
07.10.2015, 18:38:34
    #39071137
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация запроса (выборка 1 значения из 4 таблиц)
Мне так навскидку кажется, что основные проблемы создают OR-ы в секции отбора.
Думаю, можно попробовать их разделить, при этом получится 4 отдельных запроса, которые потом соединяются через UNION ALL.
Насколько при этом получится оптимизировать частные запросы для условия с подзапросом - честно говоря, думать лениво, но от функций желательно постараться избавиться, если получится (а мне почему-то кажется, что привести их к виду, когда можно создать подходящий индекс - можно). Остальные два точно оптимизируются прекрасно созданием подходящих индексов.
...
Рейтинг: 0 / 0
07.10.2015, 19:13:43
    #39071172
miksoft
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация запроса (выборка 1 значения из 4 таблиц)
grecha10
Код: sql
1.
(rub.path LIKE (SELECT CONCAT(path,'/%') FROM hdbk_rubrics WHERE id = '$idRubric') OR rub.id='$idRubric')

Что-то я не улавливаю смысл этого фрагмента. Зачем он, если "Каждому товару из catalog соответствует строго одна рубрика из hdbk_rubrics, строго конечная в ветке (без детей)." ?
Почему не написать просто c.idRubric='$idRubric' (а таблицу рубрик вовсе не использовать в запросе) ?
...
Рейтинг: 0 / 0
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Оптимизация запроса (выборка 1 значения из 4 таблиц) / 3 сообщений из 3, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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