Модераторы: skyboy
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Оптимизация запроса. Оптимизация запроса. 
:(
    Опции темы
EnMac
Дата 14.4.2015, 19:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 12.8.2009

Репутация: нет
Всего: нет



Здравствуйте.

Прошу помощи в оптимизации sql-запроса.
Описание:
Есть 2 таблицы SprTovar и Sklad
Необходимо сформировать выборку содержащую информацию о всех товарах и остатков по ним.
SprTovar - справочная таблица по всем товарам, в которой есть поля типа Kod, Name и прочее.
Sklad - таблица остатков. В эту таблицу заносится информация по кол-ву товара на определенную дату при условии что на эту дату было движение.
Т.е. например Яблоко.
01.01.2015 остаток = 100 шт
10.01.2015 был приход в кол-ве 200 шт.
15.01.2015 было реализовано 50 шт

В таблице Sklad касаемо это товара будут следующие записи
01.01.2015   100 (т.е. изначальный остаток)
10.01.2015   300 (включая приход +200)
15.01.2015   250 (минус реализация -50)

При добавлении товара в какой либо документ, необходимо отображать весь список товаров с указанием остатков по каждой записи. Необходимо учитывать что записи об остатках в таблице Sklad может и не быть.
Для выборки использую такой запрос:

Код

select a.*, c.Kol as Ostatok from SprTovar a
   left outer join (select b.DATA, b.KodTov, Sklad.Kol
                           from (select MAX(DATA) as DATA, KodTov
                                        from Sklad
                                        where KodSklad=0
                                          and DATA<='14.04.2015'
                                        group by KodTov
                                ) b,
                                Sklad
                           where b.KodTov=Sklad.KodTov
                             and b.DATA=Sklad.DATA
                             and Sklad.KodSklad=0
                    ) c ON a.KOD=c.KodTov
order by lower(a.Name)


Описание ключевых полей
Sklad.DATA - дата, на которое сформирован остаток
Sklad.KodTov - уникальный код товара
Sklad.Kol - количество на дату
Sklad.KodSklad - код склада на котором хранится товар.
SprTovar.Kod - код товара
SprTovar.Name - наименование товара
Индексы Sklad (KodTov, Data, KodSklad), SprTovar (Kod, Name)

Выборка выполняется верно. Но!
Не устраивает скорость выборки. При 5000 записей в таблице SprTovar и 300000 записей в таблице Sklad (информация за 3 года) запрос выполняется около 10 секунд. Хотелось бы ускорить процесс выборки.
Прошу помощи в оптимизации sql-запроса... 
Также рад выслушать замечания об эффективном хранении остатков товаров.

Спасибо за потраченное время. smile

Это сообщение отредактировал(а) EnMac - 14.4.2015, 20:09
PM MAIL   Вверх
Akina
Дата 14.4.2015, 22:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 45
Всего: 454



Цитата(EnMac @  14.4.2015,  20:07 Найти цитируемый пост)
При добавлении товара в какой либо документ, необходимо отображать весь список товаров с указанием остатков по каждой записи. 

Если верить тому, что написано ранее - то это просто показать максимальную дату для товара и соответствующее этой дате количество.

Цитата(EnMac @  14.4.2015,  20:07 Найти цитируемый пост)
записи об остатках в таблице Sklad может и не быть.

Т.е. товар в справочнике есть, но в наличии его нет, фактически количество = 0. так?

Цитата(EnMac @  14.4.2015,  20:07 Найти цитируемый пост)
Для выборки использую такой запрос:

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

Цитата(EnMac @  14.4.2015,  20:07 Найти цитируемый пост)
Хотелось бы ускорить процесс выборки.

Значит, так. 
Во-первых, указывайте точно, какая СУБД (да и вообще непонятно, какого хрена явно СУБД-специфичная тема делает в общем разделе). И не только фамилию, но и версию.
Во-вторых, показывайте полностью DDL таблиц.


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
EnMac
Дата 14.4.2015, 22:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 12.8.2009

Репутация: нет
Всего: нет



1. Необходимо отобразить весь справочник товаров + остатки на указанную дату (в большинстве случаев это текущая дата). Т.е. в справочнике информация по 5000 товарам, а в таблице остатков информация может быть по 4800 кол-ве товаров.
2. Да, товар в справочнике есть, но записи об этом в таблице остатков нет. Ну раз нет в таблице остатков записи, значит 0.
3. Посмотрите пожалуйста запрос, и поправьте что не так.
4. СУБД Advantage Database версия 9.10.0.35,а также Firebird v 2.5. Запрос работает на двух СУБД.
Почему я не в той теме разместил? Стандартный sql-запрос...
PM MAIL   Вверх
Akina
Дата 15.4.2015, 09:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 45
Всего: 454



Цитата(EnMac @  14.4.2015,  23:39 Найти цитируемый пост)
Почему я не в той теме разместил? Стандартный sql-запрос... 

Нет в нём ничего стандартного. Оптимальное его решение - с использованием оконных функций. Типа 
Код

SELECT a.*, COALESCE(b.col,0) ostatok, ROW_NUMBER() OVER (PARTITION BY a.code ORDER BY b.date DESC) rn
FROM a LEFT JOIN b ON ...
WHERE b.date <= #....# AND rn = 1

Но съест ли это твоя СУБД?

Это сообщение отредактировал(а) Akina - 15.4.2015, 09:14


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
RusA
Дата 15.4.2015, 10:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 0
Регистрация: 27.11.2007

Репутация: нет
Всего: нет



Стоит посмотреть план запроса. Возможно не хватает индексов по полям.

Этот ответ добавлен с нового Винграда - http://vingrad.com
PM MAIL   Вверх
EnMac
Дата 15.4.2015, 10:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 12.8.2009

Репутация: нет
Всего: нет



Цитата(Akina @ 15.4.2015,  09:09)
Оптимальное его решение - с использованием оконных функций. Типа 
Код

SELECT a.*, COALESCE(b.col,0) ostatok, ROW_NUMBER() OVER (PARTITION BY a.code ORDER BY b.date DESC) rn
FROM a LEFT JOIN b ON ...
WHERE b.date <= #....# AND rn = 1

Но съест ли это твоя СУБД?

Akina.

Понимаю, что прошу многого, но могли бы Вы, если не сложно написать завершенный (рабочий) запрос для моего случая. Просто не могу додумать Вашу идею.

Заранее, спасибо.

Это сообщение отредактировал(а) EnMac - 15.4.2015, 11:04
PM MAIL   Вверх
Akina
Дата 15.4.2015, 11:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 45
Всего: 454



А что, неужели так сложно дописАть условия связывания и отбора? Тем более что в первом посте они присутствуют...


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
EnMac
Дата 15.4.2015, 11:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 12.8.2009

Репутация: нет
Всего: нет



Цитата(Akina @ 15.4.2015,  11:19)
А что, неужели так сложно дописАть условия связывания и отбора? Тем более что в первом посте они присутствуют...

Допишу конечно.

p.s. Не поддерживает СУБД ADS такие команды

Это сообщение отредактировал(а) EnMac - 15.4.2015, 13:06
PM MAIL   Вверх
tzirechnoy
Дата 16.4.2015, 14:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1173
Регистрация: 30.1.2009

Репутация: 2
Всего: 16



Да нормальный запрос, никакого бонуса от оконных функцый обычно не будет.

А вот что СУБД часто не умеют оптимизировать ситуацыю, когда единственная агрегатная функцыя -- MAX -- это да. Потому вместо MAX(...) лучшэ поставить без группировки, но ORDER BY DATA DESC LIMIT 1 -- тогда выборка будет как раз одного элемента по индэксу.

Ну, и индэкс KodTov, Data на таблицэ Sklad, безусловно, должэн быть -- иначе будет full scan таблицы в любом случае.
PM MAIL   Вверх
victor201538
Дата 19.4.2015, 10:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 19.4.2015

Репутация: нет
Всего: нет



PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Составление SQL-запросов | Следующая тема »


 




[ Время генерации скрипта: 0.0768 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.