powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / Дата последнего движения
31 сообщений из 31, показаны все 2 страниц
Дата последнего движения
    #32883435
Crimean
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть в бухучете всякая отчетность, которая требует печать "даты последнего движения". Встал вопрос оптимизации алгоритма расчета этой самой даты. Самое интересное, что ничего путного сделать не получилось! Тривиальный запрос типа

Код: plaintext
SELECT AccountId, MAX( Date ) FROM Turns WHERE Date < @Date

приводит к сканированию таблицы оборотов / проводок (кому как приятнее - вопрос достаточно абстрактный). И это понятно - я про сканирование всей таблицы. По счету могло вообще не быть движения, а могло быть движение вчера. Соответственно, никаких критериев по ограничению мощности выборки нет. Да, есть мифическое условие "Date < @Date", но чем дальше живет система, тем чаще строят такие отчеты за последние дни, так что этим условием можно как бы и пренебречь.

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

Есть, конечно, рабочая версия - строить "опорные" таблицы дат последнего движения. Скажем, раз в год или раз в квартал, это не суть важно. Важно, что такие "опорные" таблицы существенно улучшат выполнение запроса за счет того, что будут ограничивать выборку. Но это все как-то некузяво...
...
Рейтинг: 0 / 0
Дата последнего движения
    #32883510
Alexey Sh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А что, по всем AccountId сразу нужны данные?
...
Рейтинг: 0 / 0
Дата последнего движения
    #32883668
MX-ALEX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CrimeanЕсть в бухучете всякая отчетность, которая требует печать "даты последнего движения". Встал вопрос оптимизации алгоритма расчета этой самой даты. Самое интересное, что ничего путного сделать не получилось! Тривиальный запрос типа

Код: plaintext
SELECT AccountId, MAX( Date ) FROM Turns WHERE Date < @Date

приводит к сканированию таблицы оборотов / проводок (кому как приятнее - вопрос достаточно абстрактный). И это понятно - я про сканирование всей таблицы. По счету могло вообще не быть движения, а могло быть движение вчера. Соответственно, никаких критериев по ограничению мощности выборки нет. Да, есть мифическое условие "Date < @Date", но чем дальше живет система, тем чаще строят такие отчеты за последние дни, так что этим условием можно как бы и пренебречь.

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

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

Лет 15 назад сделали вспомогательную таблицу timeStamp-index
-все вводимые-удаляемые записи синхронно отражаются в этой таблице.
Очень помогает - например связать репликациями разные базы данных
или Ваш вариант запроса - мгновенный ответ.
Ресурсов ест мало - хранится только штамп и индекс.
Считаем это обязательно должно быть
в любой вводимой руками базе.

Правда - работаем с древовидной базой данных - а не с реляционной.
...
Рейтинг: 0 / 0
Дата последнего движения
    #32883818
Фотография Dogen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CrimeanЕсть в бухучете всякая отчетность, которая требует печать "даты последнего движения". Встал вопрос оптимизации алгоритма расчета этой самой даты. Самое интересное, что ничего путного сделать не получилось! Тривиальный запрос типа

Код: plaintext
SELECT AccountId, MAX( Date ) FROM Turns WHERE Date < @Date

приводит к сканированию таблицы оборотов / проводок (кому как приятнее - вопрос достаточно абстрактный). И это понятно - я про сканирование всей таблицы. По счету могло вообще не быть движения, а могло быть движение вчера. Соответственно, никаких критериев по ограничению мощности выборки нет. Да, есть мифическое условие "Date < @Date", но чем дальше живет система, тем чаще строят такие отчеты за последние дни, так что этим условием можно как бы и пренебречь.

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

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

Я, конечно, не доктор, но у Вас индексы по номеру счета и по дате построены? Как-то неловко даже спрашивать - но если индексы помещаются в RAM сервера то должно быть пофигу какого размера таблица проводок. Или у вас сотни тысяч субсчетов?..

Использование же журнала работы по сути мало отличается от обсчета таблицы проводок, т.к. количество записей имеет один порядок.
...
Рейтинг: 0 / 0
Дата последнего движения
    #32883903
aleks2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
[quot Crimean]

Код: plaintext
SELECT AccountId, MAX( Date ) FROM Turns WHERE Date < @Date

quot]

Чегой-то такой запрос сервер посылает... требует чего-нибуть вроде

Код: plaintext
SELECT AccountId, MAX( Date ) FROM Turns WHERE Date < @Date GROUP BY AccountId

В этом случае могет помочь индекс (Date, AccountId). Сканироваться будет индекс и только в части Date < @Date.
...
Рейтинг: 0 / 0
Дата последнего движения
    #32883969
Crimean
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Данные нужны, конечно, не по всем счетам - есть и закрытые и бездействующие и технические. Скажем так, данные нужны по 1/3 ... 1/2 счетов.

TimeStamp есть, а толку? Как он поможет выичслить дату последнего движения? Да еще и на любую дату?

Индексы есть все возможные и невозможные. Для определенности - кластерный по счету и некластерный по дате. Попытки насоздавать кучу покрывающих индексов по всем возможным комбинациям полей картину с приведенным запросом не изменили (да и не могли).

Конечно GROUP BY, сорри, заработался, но сути дела это не меняет :)

aleks2Сканироваться будет индекс и только в части Date < @Date

Безусловно! Но все же (извините за самоцитирование)

CrimeanДа, есть мифическое условие "Date < @Date", но чем дальше живет система, тем чаще строят такие отчеты за последние дни, так что этим условием можно как бы и пренебречь

То есть, это условие, конечно, работает. Но - отсекает один - два дня, что на фоне 10 - 15 лет мало помогает :)

В аналогичной ситуации с остатками перешли на хранение остатков по счетам за те дни, когда были остатки или обороты. Это существенно помогло. Правда, отожрав место. Ну и пришлось построить механизм контроля актуальности и пересчета по запросу. Но, как показала практика, оно того стоило. Работа, все же, чаще идет последними несколькими днями.
...
Рейтинг: 0 / 0
Дата последнего движения
    #32884010
gardenman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тоже интересный случай: По валютным счетам - переоценка может идти хоть каждый день, а на самом деле движение по счету было пол года назад. У нас пока мы с Диасофта на свою систему не перешли с этим постоянно были проблемы.
...
Рейтинг: 0 / 0
Дата последнего движения
    #32884036
Crimean
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 gardenman

А сейчас куда проблема делась? Или таки за каждый день храните? Или не паритесь затратами на расчет?
...
Рейтинг: 0 / 0
Дата последнего движения
    #32884052
LSV
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А если строить/достраивать раз в день отдельную таблицу типа: AccountId,Date (smalldatetime) кластерный индекс.
Достройка займет пару минут ночью. Можно достраивать триггером (по вкусу).
ИМХО, не будет тормозить даже через 10лет.
В конце концов эти цифры не нужны за 10лет. Можно и резать :)
...
Рейтинг: 0 / 0
Дата последнего движения
    #32884059
Фотография Dogen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
gardenmanТоже интересный случай: По валютным счетам - переоценка может идти хоть каждый день, а на самом деле движение по счету было пол года назад. У нас пока мы с Диасофта на свою систему не перешли с этим постоянно были проблемы.
А в чем, собственно, проблема, все равно нужно иметь валютные остатки (хранить их или считать на лету - неважно.
Переоценка выполняется проводками. Они Вам что, мешают? Они ведь не проходят по аналитической ведомости, выведенной в валюте счета.
...
Рейтинг: 0 / 0
Дата последнего движения
    #32884066
gardenman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ой, не хочу все описывать заново поищите по форуму. Топик назывался "Литература"
...
Рейтинг: 0 / 0
Дата последнего движения
    #32884586
Crimean
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мдя. 5 страниц выдает в результате поиска по слову "Литература", но ничего, корелирующего с данным топиком, не нашел.
...
Рейтинг: 0 / 0
Дата последнего движения
    #32884636
Фотография Dogen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CrimeanМдя. 5 страниц выдает в результате поиска по слову "Литература", но ничего, корелирующего с данным топиком, не нашел.
Это мифический топик.
Попросите администраторов поискать, мне тоже интересно.
До сих пор про мультивалютный учет я ничего умного не увидел, разнообразные доморощенные решения без стройного логического описания :))
...
Рейтинг: 0 / 0
Дата последнего движения
    #32884701
Crimean
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Про мультивалютный учет - предлагаю завести отдельный топик :) И в этом топике считать оффтопиком :) У меня вполне технический вопрос - как не аргерировать всю таблицу. Вариант с хранением не катит - очень дорого в хранении. Пока рабочих (и работающих) вариантов немного - или существенное ограничение количества счетов в отчете или хренение "срезов" дат последнего движения хотя бы несколько штук за год. Скажем, раз в месяц. Это немного даже для 10 лет (всего ~ 40 * количество счетов, это терпимо), а определенный выигрышь дает, скажем, срез на начало года (я понимаю, прошел всего месяц) прозволят сократить затраты с

4203 CPU 49171 Reads при 16.7 секундах (много!)
до
1985 CPU 5261 Reads при 5.6 секундах (все равно много!)

Что уже вполне неплохо. Подозреваю, что можно еще как-нить это упростить.
...
Рейтинг: 0 / 0
Дата последнего движения
    #32884704
gardenman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
/topic/102032&hl=
/topic/103177&hl=#770153
...
Рейтинг: 0 / 0
Дата последнего движения
    #32884746
Фотография Dogen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
gardenman/topic/102032&hl=
/topic/103177&hl=#770153
Искренне советую найти валютного бухгалтера или кассира банка и расспросить его о практике валютного учета. Из первых рук, ткскзть. Можно, конечно, почитать означенные топики. В один я дописал.
...
Рейтинг: 0 / 0
Дата последнего движения
    #32884851
Crimean
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 gardenman

И что в этих топиках поможет "оптимизации алгоритма расчета этой самой даты"? Про мультивалютность и про основы учета я не спрашивал. Как бы не факт, что мой вопрос вообще про бухучет. Просто похожая задача.
...
Рейтинг: 0 / 0
Дата последнего движения
    #32886278
aleks2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну насчет отсутствия пользы индексов:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
таблица dbo.Counter
~ 800  уникальных (СontrollerN, SerialN)
~ 50   000  записей до '20041101'

declare @date datetime
set @date='20041101'
SELECT СontrollerN, SerialN, MAX(Data) AS Data
FROM  dbo.Counter
WHERE (Data > @Date)
GROUP BY СontrollerN, SerialN

CPU~ 120  - без индексов
  |--Hash Match(Aggregate, HASH:([Counter].[СontrollerN], [Counter].[SerialN]), RESIDUAL:([Counter].[СontrollerN]=[Counter].[СontrollerN] AND [Counter].[SerialN]=[Counter].[SerialN]) DEFINE:([Expr1002]=MAX([Counter].[Data])))
       |--Clustered Index Scan(OBJECT:([NostraLink].[dbo].[Counter].[PK_Counter]), WHERE:([Counter].[Data]>[@date]))

CPU~ 100  - с индексом (СontrollerN, [SerialN], Data)
  |--Stream Aggregate(GROUP BY:([Counter].[СontrollerN], [Counter].[SerialN]) DEFINE:([Expr1002]=MAX([Counter].[Data])))
       |--Index Scan(OBJECT:([NostraLink].[dbo].[Counter].[IX_Counter_CN_SN_Date]),  WHERE:([Counter].[Data]>[@date]) ORDERED FORWARD)

CPU~ 70  - с индексом (Data, СontrollerN, [SerialN])
  |--Hash Match(Aggregate, HASH:([Counter].[СontrollerN], [Counter].[SerialN]), RESIDUAL:([Counter].[СontrollerN]=[Counter].[СontrollerN] AND [Counter].[SerialN]=[Counter].[SerialN]) DEFINE:([Expr1002]=MAX([Counter].[Data])))
       |--Index Seek(OBJECT:([NostraLink].[dbo].[Counter].[IX_Counter_Date_CN_SN]), SEEK:([Counter].[Data] > [@date]) ORDERED FORWARD)
...
Рейтинг: 0 / 0
Дата последнего движения
    #32886298
aleks2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пардон, неверно переписал

WHERE (Data > @Date)

следует читать

WHERE (Data < @Date)
...
Рейтинг: 0 / 0
Дата последнего движения
    #32886447
Crimean
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 aleks2

Если бы вопрос был техническим - он был бы задан в профильной конференции :) Все возможные и невозможные индексы есть. Объемы слегка не те. Счетов ~полмиллиона, оборотов ~ 10 миллионов. За менее чем 10 лет. Распределение неравномерное - с увеличением даты количество оборотов в день растет.

Важна не конкретная выборка, важен принцип. В указанном запросе невозможно в принципе избавиться от сканирования всей таблицы сначала до указанной даты. Я ищу способ ДЕШЕВО от такого сканирования избавиться. Пока - теоретический. Рабочие варианты я указал. Они дают определенный выигрышь, но есть подозрение, что не вижу чего-то очевидного. Для этого и спрашиваю.
...
Рейтинг: 0 / 0
Дата последнего движения
    #32886924
Фотография Dogen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Crimean2 aleks2

Если бы вопрос был техническим - он был бы задан в профильной конференции :) Все возможные и невозможные индексы есть. Объемы слегка не те. Счетов ~полмиллиона, оборотов ~ 10 миллионов. За менее чем 10 лет. Распределение неравномерное - с увеличением даты количество оборотов в день растет.

Важна не конкретная выборка, важен принцип. В указанном запросе невозможно в принципе избавиться от сканирования всей таблицы сначала до указанной даты. Я ищу способ ДЕШЕВО от такого сканирования избавиться. Пока - теоретический. Рабочие варианты я указал. Они дают определенный выигрышь, но есть подозрение, что не вижу чего-то очевидного. Для этого и спрашиваю.
Вообще начинают терзать смутные сомнения, что это нужно. Что за база у Вас такая? Она ведь явно не используется в оперативной работе, а отчета можно и подождать.

Слуушайте, а Вы не связаны с госорганами - с украинской налоговой, например? Я помню когда была там тема про ИНН или что-то вроде него, я прикидывал в уме потребный объем/стоимость железа для обработки данных, которые они собрать хотели. Мне смешно было.

Может, НЕ НУЖНА такая база и Вы решаете проблемы, которые на другом уровне надо было решать? Например, работать на местах с базами меньшего размера?

Мне вот интересно, сеть Walmart (могу ошибаться) накапливает чуть не терабайты данных в день (о розничных продажах), так они тоже это обсчитывают в онлайн или как
...
Рейтинг: 0 / 0
Дата последнего движения
    #32886955
Crimean
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Dogen

Вопрос как раз в минимизации времени "подождать". Или смысл проблемы до сих пор остался неясным? Со временем будет неконтролируемый рост времени расчета, от чего хочется уйти.

Ну и то, что Вас терзают смутные сомнения в необходимости никак не уберет эту самую необходимость. Она вполне себе материальна :)
...
Рейтинг: 0 / 0
Дата последнего движения
    #32887996
Фотография PVP
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Для частого поиска последней операции можно создать специальный индекс с сортировкой по убыванию

CREATE INDEX IX_OPR1_REW ON dbo.OPR1(DateOpr DESC, NomOpr DESC )

затем использовать оператор

-- просто последняя операция
Select top 1 NomOpr
from Opr1 with (index(Ix_Opr1_Rew))
order by DateOpr Desc

-- последняя до заданного события, например в текущем месяце
Select top 1 NomOpr
from Opr1 with (index(Ix_Opr1_Rew))
where DateOpr<'31.12.04'
order by DateOpr Desc

Выборка происходит мгновенно не зависимо от размера таблицы
...
Рейтинг: 0 / 0
Дата последнего движения
    #32888009
Crimean
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 PVP

А для ВСЕХ операций? Для ОДНОЙ я и сам могу.

Для всех - да, как-то неочевидно получилось, что отчет строится по ВСЕМ счетам или по бОльшей их части. В определении этой самой даты для одного счета проблем нет никаких совершенно.
...
Рейтинг: 0 / 0
Дата последнего движения
    #32888015
Фотография Dogen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Crimean2 Dogen

Вопрос как раз в минимизации времени "подождать". Или смысл проблемы до сих пор остался неясным? Со временем будет неконтролируемый рост времени расчета, от чего хочется уйти.

Ну и то, что Вас терзают смутные сомнения в необходимости никак не уберет эту самую необходимость. Она вполне себе материальна :)
Как это неконтролируемый? Будет типа какой-нибудь логарифм от количества документов (пущай грамотные товарищи поправют).
...
Рейтинг: 0 / 0
Дата последнего движения
    #32888046
Alexey Rovdo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
DogenКак это неконтролируемый? Будет типа какой-нибудь логарифм от количества документов (пущай грамотные товарищи поправют).

Логарифм он и есть логарифм. И результат логарифма уж точно неконтролируемый - он предопределенный законами природы.
...
Рейтинг: 0 / 0
Дата последнего движения
    #32888056
Alexey Rovdo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А может построить отдельную таблицу, в которую переносить только уникальные значения пар AccountId и Date? Т.е. множество проводок по одному счету в один день породят в такой таблице только одну запись. Не уверен, что это отличается от использования композитных индексов, но в такой таблице в любом разе легче будет задействовать кластеризацию.
...
Рейтинг: 0 / 0
Дата последнего движения
    #32888068
Crimean
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторА может построить отдельную таблицу

И чего? Будет сканиться она. Получим неконтролируемый рост / количество записей в день = неконтролируемый рост.
...
Рейтинг: 0 / 0
Дата последнего движения
    #32888075
Фотография PVP
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
-- Если есть разные счета, тогда надо использовать код операции
CREATE INDEX IX_OPR1_REW ON dbo.OPR1(KofOpr, DateOpr DESC, NomOpr DESC )

-- Использовать временную таблиицу или таблицу памяти
Declare @DateN DateTime, @DateK DateTime
Create table #T (KodOPr int, DateOpr DateTime, NomOpr int)
Insert into #T (KodOpr)
select Distinct KodOpr
from Opr1 with (index(Ix_Opr1_Rew))
where DateOpr between @DateN and @DateK
-- Здесь нет перебора по базе, используется только индекс

-- Заполнить таблицу последней датой
Update t Set
DateOpr=(select top 1 DateOpr
from Opr1 with (index(Ix_Opr1_Rew))
order by DateOpr Desc, NomOpr desc),
NomOpr=(select top 1 DateOpr
from Opr1 with (index(Ix_Opr1_Rew))
order by DateOpr Desc, NomOpr desc)
from #T t

-- Можно еще уменьшить время в два раза, если помудрить
-- над последним операторм, т.е.

Declare @Str VarChar (50)
Update t Set
@Str =(select top 1
Convert(Char(15),DateOpr,4)+
Convert(Char(10), NomOpr)
from Opr1 with (index(Ix_Opr1_Rew))
order by DateOpr Desc, NomOpr desc),
DateOpr=Convert(DateTime,Left(@Str,15)),
NomOpr=Convert(Int,Substring(@Str,16,10))
from #T t
...
Рейтинг: 0 / 0
Дата последнего движения
    #32888791
Crimean
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 PVP

Спасибо! И ведь знал же про этот прием... Избавил от кучи лишней работы. Reads, конечно, в результате бы революционно уменьшилось, но так (через спекуляцию с индексом) все будет работать уже сейчас и без изменения системы.

P.S.В "моем" случае и DESC индекса не понадобилось по своим причинам.
...
Рейтинг: 0 / 0
Дата последнего движения
    #32889527
funikovyuri
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Crimean

Обычно кроме проводок есть еще и закэшированная информация об остатках на счете
При чем если ее делать по уму то эта таблица, грубо говоря, хранит записи только за
те даты на которые по указанному счету были обороты. Ясно, что количество записей в
такой таблице на порядок меньше чем в таблице проводок. Возможно, стоит требуемую
информацию брать оттуда?

Это что касается программной оптимизации - кроме того, у большинства СУБД есть свои
средства работы с большими таблицами (тот же partitioned views)
...
Рейтинг: 0 / 0
31 сообщений из 31, показаны все 2 страниц
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / Дата последнего движения
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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