powered by simpleCommunicator - 2.0.49     © 2025 Programmizd 02
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / помогите максимально оптимизировать
25 сообщений из 47, страница 1 из 2
помогите максимально оптимизировать
    #40057013
GrigoriyFomin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Есть рабочая таблица с остатками товара, где хранятся остатки на каждый день.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
CREATE TABLE AMOUNTS (
    CAID    D_ID NOT NULL /* D_ID = INTEGER */,
    MODID   D_ID NOT NULL /* D_ID = INTEGER */,
    ADATE   D_DATE DEFAULT 'now' NOT NULL /* D_DATE = DATE */,
    MODCNT  D_PRICE /* D_PRICE = NUMERIC(15,2) */
);

ALTER TABLE AMOUNTS ADD CONSTRAINT PK_AMOUNTS PRIMARY KEY (CAID, MODID, ADATE);

CREATE INDEX AMOUNTS_IDX1 ON AMOUNTS (MODID);



CAID - ИД объекта (склад, магазин)
MODID - ИД товара
ADATE - дата обновления остатков
MODCNT - количество на остатках

Есть процедура, которая дает определенное количество товара на любую дату.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
create or alter procedure GETAMOUNTS4MODID (
    ACAID_ D_ID,
    MODID_ D_ID,
    ADATE_ D_DBDATE)
returns (
    MODCNT D_PRICE)
as
begin
  select MODCNT
  from AMOUNTS AA
  where (CAID = :ACAID_) and
        (MODID = :MODID_) and
        (ADATE = (select max(ADATE)
                  from AMOUNTS A1
                  where (A1.CAID = :ACAID_) and
                        (A1.MODID = :MODID_) and
                        A1.ADATE <= :ADATE_))
  into :MODCNT;
  suspend;
end


Есть - которая дает все ненулевые остатки на дату.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
create or alter procedure GETAMOUNTS (
    ADATE D_DATE,
    CAID D_ID)
returns (
    MODID_ D_ID,
    ADATE_ D_DATE,
    MODCNT_ D_PRICE)
as
begin
  for select AA.MODID, AA.ADATE, AA.MODCNT
      from AMOUNTS AA
      where (AA.CAID = :CAID) and
            (AA.ADATE = (select max(ADATE)
                         from AMOUNTS A1
                         where (A1.CAID = :CAID) and
                               (A1.MODID = AA.MODID) and
                               (A1.ADATE <= :ADATE)))
      into :MODID_, :ADATE_, :MODCNT_
  do
    suspend;
end




Как эти запросы можно оптимизировать? И как можно получить более оптимально ПОСЛЕДНИЕ остатки( текущие). Код работает 7 лет уже, что еще можно наоптимизировать - ума не приложу. Сейчас таблица остатков имеет 4,5 млн записей и получить текущие остатки на магазине например, занимает неприлично много времени.
...
Рейтинг: 0 / 0
помогите максимально оптимизировать
    #40057015
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GrigoriyFomin,

В GETAMOUNTS4MODID - нужен SELECT FIRST 1 ORDER BY CAID DESC, MODID DESC, ADATE DESC
и индекс
CREATE DESCENDING INDEX AMOUNTS_DESC ON AMOUNTS (CAID, MODID, MODID);

Во 2-й процедуре - нужен SELECT по таблице товаров и JOIN GETAMOUNTS4MODID(...) ON 1=1
...
Рейтинг: 0 / 0
помогите максимально оптимизировать
    #40057030
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GrigoriyFomin,

планы и статистика выполнения - где ?
...
Рейтинг: 0 / 0
помогите максимально оптимизировать
    #40057049
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Привет.

Сейчас таблица остатков имеет 4,5 млн записей и получить текущие остатки на магазине например, занимает неприлично много времени.
Я так понимаю, нарекания вызывает время выполнения процедуры GETAMOUNTS?

Идея заключается в том, что бы в цикле определять максимальную дату для каждого товара,
а потом по этому товару и максимальной дате извлекать остатки:
Код: 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.
create or alter procedure GETAMOUNTS (
    ADATE D_DATE,
    CAID D_ID)
returns (
    MODID_  D_ID,
    ADATE_  D_DATE,
    MODCNT_ D_PRICE)
as
begin
  for
    select a.MOID,
           max ( a.ADATE )
      from AMOUNTS a
     where a.CAID  = :CAID
       and a.ADATE <= :ADATE
     group by a.MOID
      into :MODID_,
           :ADATE_
  do
  begin
    MODCNT_ = ( select MODCNT
                  from AMOUNTS
                 where CAID  = :CAID
                   and MODID = :MODID_
                   and ADATE = :ADATE_ );
    suspend;
  end
end



Ну, и убывающий индекс по дате будет не лишним )
Код: sql
1.
create descending index IDX_AMOUNTS_ADATE on AMOUNTS ( ADATE );
...
Рейтинг: 0 / 0
помогите максимально оптимизировать
    #40057051
Фотография Старый плюшевый мишка
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GrigoriyFomin

Как эти запросы можно оптимизировать? И как можно получить более оптимально ПОСЛЕДНИЕ остатки( текущие). Код работает 7 лет уже, что еще можно наоптимизировать - ума не приложу. Сейчас таблица остатков имеет 4,5 млн записей и получить текущие остатки на магазине например, занимает неприлично много времени.


На такой структуре уж совсем шустренько текущие остатки никак не получить. У коллеги YuRock там описочка в индексе, имелось в виду, конечно, CREATE DESCENDING INDEX AMOUNTS_DESC ON AMOUNTS (CAID, MODID, ADATE), это даст выигрыш, но незначительный. Эта структура - журнал остатков, скорее, даже не остатков, а операций с остатком после выполнения операции. Она хороша для необходимых , но относительно редких запросов по остаткам на произвольную дату, с которыми можно и потерпеть. А текущие остатки надо хранить в таблице без истории. И можно, если журнал действительно не содержит никаких ссылок-атрибутов насчёт операций, приводящих к изменениям остатков, из приложения вносить изменения только в эту таблицу, а журнал вести на её триггерах.

ЗЫ Чота я в последние дни рас... рас... разболтался, короче, надо и честь знать
...
Рейтинг: 0 / 0
помогите максимально оптимизировать
    #40057056
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Старый плюшевый мишка
(CAID, MODID, ADATE)
Да, благодарю
...
Рейтинг: 0 / 0
помогите максимально оптимизировать
    #40057074
Barkan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GrigoriyFomin,

Как вариант - заведите под текущие остатки отдельную табличку.
...
Рейтинг: 0 / 0
помогите максимально оптимизировать
    #40057081
Фотография Exteris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
История остатков за какой период? Если 7 лет, то зачем? Можно хранить остатки за последний месяц, например. Все старые агрегировать, как начальный остаток.
...
Рейтинг: 0 / 0
помогите максимально оптимизировать
    #40057086
WildSery
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Старый плюшевый мишка
ЗЫ Чота я в последние дни рас... рас... разболтался, короче
Для чего же ещё нужон форум?!
...
Рейтинг: 0 / 0
помогите максимально оптимизировать
    #40057253
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вариант: хранить только текущие остатки в отдельной таблице. Имея историю операций, можно легко вычислить остаток на любую дату.
...
Рейтинг: 0 / 0
помогите максимально оптимизировать
    #40057255
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Этот вариант во-первых, сделает создаст очередь к записи в таблице, а во-вторых затормозит
получение остатков до O(N).
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
помогите максимально оптимизировать
    #40057266
GrigoriyFomin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Exteris
История остатков за какой период? Если 7 лет, то зачем? Можно хранить остатки за последний месяц, например. Все старые агрегировать, как начальный остаток.

ну не все товары продаются сразу, если товар сезонный, он может по 9 месяцев на складе ждать своего сезона, некоторые позиции годами не продаются. В свое время просто количество товара было пару тысяч и операций - 20тыс., а сейчас со временем все выросло на порядки! Щас сделал таблицу временных остатков, но ее формирование занимает 3-4 минуты на неслабом железе. Когда делалась такая структура хотелось уйти от операции "закрыть день" или "сохранить остатки на конец дня". Так получается рантаймовый сопосб получить остатки на любой день и соотв. выводить товарный отчет за любой период.
...
Рейтинг: 0 / 0
помогите максимально оптимизировать
    #40057269
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov

Этот вариант во-первых, сделает создаст очередь к записи в таблице, а во-вторых затормозит
получение остатков до O(N).


Мы так сделали. Работает быстро, если не пытаться получить остаток годичной давности. Обычно нужно знать текущий остаток. Иногда на начало месяца. Конечно зависит от количества транзакций в базе.

Очередь транзакций это беда, если больше 4х касс. Для АЗС такого не бывает.
...
Рейтинг: 0 / 0
помогите максимально оптимизировать
    #40057299
Шавлюк Евгений
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У меня рассчитанные остатки находятся в одной таблице с движением.
Любая операция движения это 2 строки:
1) Откуда, дата, ид товара, -количество, -сумма признак "движение"
2) Куда, дата, ид товара, количество, сумма, признак "движение"

Кроме того периодически можно закрывать период. Создается запись
Место хранения, дата, ид товара, количество, сумма, признак "остаток"

Остаток на любую дату считается как сумма
Остаток на "ближайший к требуемой дате" закрытый период + движение за период от даты закрытия до текущей.
Подробнее описывал здесь и здесь
...
Рейтинг: 0 / 0
помогите максимально оптимизировать
    #40057369
ggreggory
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Шавлюк Евгений

Любая операция движения это 2 строки:


Стрёмная у вас технология - делать проводку двумя разными опосредованно связанными записями. Это всё равно что делать базу данных без внешних ключей. Вполне возможно, что программировать это легче и работает быстрее, но в надежности вашей конструкции я сомневаюсь.
...
Рейтинг: 0 / 0
помогите максимально оптимизировать
    #40057374
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ggreggoryв надежности вашей конструкции я сомневаюсь.

У меня для тебя есть новость: некоторое время назад весьма неглупые люди придумали штуку
под названием "транзакция" со свойством атомарности. И, кстати, записей на операцию может
быть гораздо больше, чем две.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
помогите максимально оптимизировать
    #40057377
ggreggory
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry Sibiryakov

И, кстати, записей на операцию может
быть гораздо больше, чем две.


Да хоть сто, на надежность это не влияет. А у него - сумма в двух экземплярах в базе. Похоже - одна для директора, а другая для своего кармана. Скажите где ваша система работает, я покажу как можно воровать.
...
Рейтинг: 0 / 0
помогите максимально оптимизировать
    #40057380
Фотография Старый плюшевый мишка
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ggreggory
Dimitry Sibiryakov

И, кстати, записей на операцию может
быть гораздо больше, чем две.


Да хоть сто, на надежность это не влияет. А у него - сумма в двух экземплярах в базе. Похоже - одна для директора, а другая для своего кармана. Скажите где ваша система работает, я покажу как можно воровать.


Точно-точно. Весь этот дурацкий бухучёт построен на принципе двойной записи, который от лукавого.
...
Рейтинг: 0 / 0
помогите максимально оптимизировать
    #40057382
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ggreggoryА у него - сумма в двух экземплярах в базе.

Не в двух. На каждый склад - своя сумма. А складов может быть много.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
помогите максимально оптимизировать
    #40057385
Фотография Старый плюшевый мишка
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GrigoriyFomin,

Кстати, безотносительно темы - всё не мог понять что мне вот здесь
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
  select MODCNT
  from AMOUNTS AA
  where (CAID = :ACAID_) and
        (MODID = :MODID_) and
        (ADATE = (select max(ADATE)
                  from AMOUNTS A1
                  where (A1.CAID = :ACAID_) and
                        (A1.MODID = :MODID_) and
                        A1.ADATE <= :ADATE_))



на уровне подсознания режет глаз, и вдруг дошло. Не знаю, может это уже и не актуально, а преданье старины глубокой, но были какие-то глюки с повторным использованием параметра во вложенном селекте. Какие - не помню, лет 15 точно уже на рефлексе пишу только так

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
  select MODCNT
  from AMOUNTS AA
  where (CAID = :ACAID_) and
        (MODID = :MODID_) and
        (ADATE = (select max(ADATE)
                  from AMOUNTS A1
                  where (A1.CAID = AA.ACAID_) and
                        (A1.MODID = AA.MODID_) and
                        A1.ADATE <= :ADATE_))



Бережёного бог бережёт.
...
Рейтинг: 0 / 0
помогите максимально оптимизировать
    #40057462
Шавлюк Евгений
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ggreggory,

Почитайте про принцип двойной записи, это будет вам полезно. Ему всего-то 700 лет.
Ну и про транзакции заодно.
На каждую операцию, как выше сказали, может быть гораздо больше чем строки, но это принцип. Азы бух.учета.
...
Рейтинг: 0 / 0
помогите максимально оптимизировать
    #40057464
Шавлюк Евгений
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть документ, а есть операции (проводки) по этому документу.
Никакого редактирования проводок отдельно от документа не существует.

Любая операция это две операции:
1) уходит со "склада А" на "сумму";
2) приходит на "склад Б" на "сумму";

Все отчеты в такой структуре тривиальные и быстрые.
...
Рейтинг: 0 / 0
помогите максимально оптимизировать
    #40059081
KreatorXXI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Шавлюк Евгений
Есть документ, а есть операции (проводки) по этому документу.
Никакого редактирования проводок отдельно от документа не существует.

Любая операция это две операции:
1) уходит со "склада А" на "сумму";
2) приходит на "склад Б" на "сумму";

Все отчеты в такой структуре тривиальные и быстрые.

А "суммы" разные? Если одинаковые, то зачем две операции?
...
Рейтинг: 0 / 0
помогите максимально оптимизировать
    #40059135
WildSery
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
KreatorXXI
А "суммы" разные? Если одинаковые, то зачем две операции?
Может, лучше вообще ничего не писать, а просто таблички на складах перевесить?
Бывают операции не парные (просто списание и просто приход). (для движений склада, не бухучёта)
А ещё, кроме склада и суммы, бывают другие реквизиты записей, и они могут различаться.
...
Рейтинг: 0 / 0
помогите максимально оптимизировать
    #40059139
WildSery
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GrigoriyFomin
И как можно получить более оптимально ПОСЛЕДНИЕ остатки( текущие).
Чтобы их получить, их необходимо хранить. В таблице остатков.

Чтобы удобно получать остатки на дату, нужно создать таблицу хранимых агрегатов (промежуточных итогов), расчёты на начало месяца, к примеру.
...
Рейтинг: 0 / 0
25 сообщений из 47, страница 1 из 2
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / помогите максимально оптимизировать
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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