On-line: гостей 1. Всего: 1 [подробнее..]
АвторСообщение





Пост N: 436
Зарегистрирован: 08.07.06
ссылка на сообщение  Отправлено: 04.04.15 02:22. Заголовок: Нужен реально компактный индекс


Добрый день.

Есть большая таблица (под 100 мегов) - выборка по товару за пару лет с такой структурой:
--
code C10 - код товара
stock I2 - код склада хранения, 32бита
date D3 - дата (компактная форма)
remain I4 - остаток товара на эту дату, 64бита
sales I4 - продано в этот день, 64 бита
--
Чтобы правильно заполнить эту таблицу на основании данных приходов/перемещений/продаж, нужно иметь индекс по "код товара+код склада+дата". Если делать "классически": INDEX ON table->code+STR(table->stock,5)+DTOS(table->date) TO... - получаем:

1) размер индексного файла становится много больше самой таблицы (23 байта индексное выражение против 15 байт одна строка таблицы)

2) после увеличения самой таблицы свыше 20 мегов - скорость добавления в нее падает очень и очень заметно. Таблица и индекс локальны и открыты монопольно.

-----

Что я подумал: а существует ли какой-то способ создания индекса на основе имеющихся, "компактных" форм хранения данных? По сути, выражение DTOS() и "приклеенный" STR() дают избыточную сортировку по дате и номеру склада, которые в момент создания этой таблицы не нужны. Нужен быстрый поиск записи по трем полям и корректировка значений.

Т.е. нужно "бинарное" значение даты и 32-битного числа.

PS: про I2BIN() и BIN2I() знаю с времен Клиппера. Вопрос - что делать с датой в данном случае и с разными "интересными" и "компактными" форматами данных, например, "@", "+" итп... - в общем ?

PPS: dbfntx

Спасибо.

Спасибо: 0 
ПрофильЦитата Ответить
Ответов - 24 , стр: 1 2 All [только новые]


постоянный участник


Пост N: 1042
Зарегистрирован: 27.01.07
ссылка на сообщение  Отправлено: 04.04.15 09:05. Заголовок: Чё-та я не врубился,..


Чё-та я не врубился, зачем такие сложности. dbfcdx не пробовал?

Спасибо: 0 
ПрофильЦитата Ответить
администратор




Пост N: 4658
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 04.04.15 09:07. Заголовок: PSP пишет: dbfcdx н..


PSP пишет:

 цитата:
dbfcdx не пробовал?


Да он где то писал , что по каким то причинам он не подходит.
Задача локальная и можно было бы прикрутить локальный ADS и юзать
индексы IDX.

Спасибо: 0 
ПрофильЦитата Ответить



Пост N: 162
Зарегистрирован: 19.05.05
ссылка на сообщение  Отправлено: 04.04.15 09:52. Заголовок: У меня в некоторых з..


У меня в некоторых задачах построены индексы NTX по двоичному полю
вроде все работает и нареканий не было

Спасибо: 0 
ПрофильЦитата Ответить
moderator


Пост N: 895
Зарегистрирован: 06.07.06
ссылка на сообщение  Отправлено: 04.04.15 10:09. Заголовок: Dima пишет: Да он г..


Dima пишет:

 цитата:
Да он где то писал , что по каким то причинам он не подходит.


Нет и не может быть таких причин.

Что до основного вопроса - можно попробовать изменить формат таблицы - заменить "интересные" типы данных на "C" - утрамбовать с помощью своих функций поля, входящие в индекс. Если размер становится критичным, стоит разбить таблицу на несколько, по годам - учитывая, что со временем она будет расти.

Спасибо: 1 
ПрофильЦитата Ответить



Пост N: 126
Зарегистрирован: 21.04.13
ссылка на сообщение  Отправлено: 04.04.15 10:11. Заголовок: Т.е. нужно "бинарное" значение даты и 32-битного числа.


Не, не нужно.
Полагаю, ложный путь. Не приведет к цели. Какая она- ускорение доступа ?
Или экономия места на диске ?
Возможно, проще изменить архитектуру - перепроектировать размещение данных в таблицах..
Таблица напоминает оперативно модифицируемый агрегатный отчет.
Зачем держать данные за два года, меняется наверняка только последний текущий месяц?
Возможно, быстрее и проще пересоздавать отчет целиком , чем поддерживать оперативный агрегат.



Спасибо: 1 
ПрофильЦитата Ответить
постоянный участник




Пост N: 543
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 04.04.15 10:11. Заголовок: Sergy надо избавить..


Sergy
надо избавиться от вычисления ключа, добавив поле ключа и заполнять его в момент образования записи, дату можно сократить до год(2) и номер дня от начала года, + полученный ключ (символьный) можно пропустить через crc32 и в ключе использовать значение от crc32, но надо посмотреть точнее, может code+str(crc32(...), 8), но это писать в поле KY и индекс простой INDEX ON KY TO ...

Спасибо: 1 
ПрофильЦитата Ответить
постоянный участник




Пост N: 544
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 04.04.15 10:53. Заголовок: PS. Даже, доспустив ..


PS. Даже, доспустив дублирование ключа, можно поменять точный подвод, на относительный
- подводим по ключу
- do while ищем точное значение на совпадение по реальным значениям полей записи
т.е. можно использовать и str(crc16(...), 5)

Спасибо: 1 
ПрофильЦитата Ответить





Пост N: 437
Зарегистрирован: 08.07.06
ссылка на сообщение  Отправлено: 04.04.15 11:29. Заголовок: Отвечу по пооядку. ..


Отвечу по порядку. С планшета, поэтому без цитат, сорри.

Почитал я реализацию dbfcdx/dbfntx в Harbour - по внутренней структуре/ограничениям между ними нет разницы. CDX лишь позволяет в одном файле хранить несколько тегов.

IDX/ADS - ради одного, пусть "гигантского" отчета прикручивать? Дадут ли они реальное увеличение именно скорости поиска среди миллионов записей? Не уверен, потому что не пробовал. Для повседневной работы с запасом хватает dbfntx.

DBFNTX у меня нормально работает с двоичными данными. В данном примере смешаны строка+дата+число

Вариант с укороченным индексом - только, например, кода товара и последующим dowhile ... skip enddo - буду пробовать тоже. Может быть, он даст прирост скорости. Спасибо.

По структуре данных - не очень понимаю, что такое "оперативно модифицируемый агрегатный расчет". Задача - заполнить таблицу товар/дата/остаток/продано за длительный период - на основании текущих остатков + журналов продаж/приходов/перемещений. Это нужно для анализа работы отдела закупщиков, более грамотного планирования пополнения складских запасов, выявления сезонности товара и тп.

Да, обновляться на регулярной основе будут данные за последние дней 10-15, тк именно в них возможны корректировки. Но ведь эти данные еще нужно быстро найти и обновить в таблице, хранящей всю эту информацию.

Разбивка на несколько таблиц по годам... Да, возможно придется пойти и по этому пути. Не хотелось-бы, тк реально анализировать более двух-трех лет вряд-ли кому понадобится.

Добавление "индексного поля" - мне кажется, один из наиболее реальных способов... Идеально было-бы получить дату в виде строки размером в три байта (в которых она хранится). Но как ?

Спасибо.

Спасибо: 0 
ПрофильЦитата Ответить



Пост N: 127
Зарегистрирован: 21.04.13
ссылка на сообщение  Отправлено: 04.04.15 11:54. Заголовок: Дата в 3 байта


Нужны же не все даты, а только за последние 2 года+ вперед на лет 10 ?
Тогда просто используйте число дней от 01.01.2010
date_beg := stod('20100101')
n:=date_x-date_beg
Ну а число дней - паковать

Спасибо: 0 
ПрофильЦитата Ответить
moderator


Пост N: 896
Зарегистрирован: 06.07.06
ссылка на сообщение  Отправлено: 04.04.15 12:00. Заголовок: Sergy пишет: Почита..


Sergy пишет:

 цитата:
Почитал я реализацию dbfcdx/dbfntx в Harbour - по внутренней структуре/ограничениям между ними нет разницы.


Cdx по определению еще со времен Клиппера - компактный индекс. Впрочем, можете проверить сами. Я вот сейчас построил для сравнения индексы к одной своей таблице:

Кол-во записей - 344600
Длина ключа - 14 байт
Размер cdx индекса - 1679K
Размер ntx индекса - 8617K


 цитата:
Идеально было-бы получить дату в виде строки размером в три байта (в которых она хранится). Но как ?


Ну, например: Chr(Year(d)-2000)+Chr(Month(d)+Chr(Day(d)
Можно и в 2 байта, если кол-во лет ограничено: Chr( (Year(d)-2012)*16 + Month(d) ) + Chr(Day(d))


Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 545
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 04.04.15 12:15. Заголовок: Sergy пишет:получить..


Sergy пишет:
 цитата:
получить дату в виде строки размером в три байта


если использовать str(crc32(cKey),8), то все равно, как получена дата - хоть словами, для данного примера (важно формировать cKey), для других индексов в других файлах alkresin прав
 цитата:
Ну, например:...



Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 546
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 04.04.15 12:26. Заголовок: Sergy пишет:Вариант ..


Sergy пишет:
 цитата:
Вариант с укороченным индексом - только, например, кода товара и последующим dowhile ... skip enddo - буду пробовать


я имел ввиду не укороченный код, а поле KY ключ, полученный str(crc32(cKey), 8) или str(crc16(cKey, 5), т.е. длина new поля KY 8 или 5 байт, а алгоритм получения строки cKey вам виднее по задаче

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 547
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 04.04.15 12:56. Заголовок: alkresin пишет:Нет и..


alkresin пишет:
 цитата:
Нет и не может быть таких причин.


если у файла dbf только один индекс (и имя индекса совпадает с dbf), то преобразовать в cdx для начала только его - не должно быть проблеммой:
REQUEST DBFCDX
в открытие этого файла добавить VIA ... и уже все должно срастись по текстам

Спасибо: 0 
ПрофильЦитата Ответить



Пост N: 128
Зарегистрирован: 21.04.13
ссылка на сообщение  Отправлено: 04.04.15 14:55. Заголовок: что такое "оперативно модифицируемый агрегатный расчет"


Задача - заполнить таблицу товар/дата/остаток/продано за длительный период - на основании текущих остатков + журналов продаж/приходов/перемещений.

А как и когда заполнить ? Однократно по требованию(отдела закупщиков) или держать постоянно готовым, а модифицировать сразу по факту каждой продажи - это пополнение отчета.
Упрощенно - факт продажи заносится в базу продаж. Если нужно узнать итоговую сумму продаж за день на текущий момент ,
создается отчет типа SUM... или TOTAL.. или Dbeval . Получаем SUMDAY
Вариант оперативного агрегата - открыто две таблицы - продаж и таблица итога(агрегат). По факту продаж дополнительно к записи в первую таблицу , сумма каждой продажи добавляется к SUMDAY во второй таблице в момент продажи.
Иногда морока с обслуживанием второй таблицы(готовый отчет) не стоит свеч. Быстрее и проще по каждому запросу(или по расписанию) заново сделать SUM.. или TOTAL..


Спасибо: 0 
ПрофильЦитата Ответить





Пост N: 438
Зарегистрирован: 08.07.06
ссылка на сообщение  Отправлено: 04.04.15 17:59. Заголовок: petr707 пишет: Нужн..


petr707 пишет:

 цитата:
Нужны же не все даты, а только за последние 2 года+ вперед на лет 10 ?
Тогда просто используйте число дней от 01.01.2010
date_beg := stod('20100101')
n:=date_x-date_beg
Ну а число дней - паковать



Да, наверное так и сделаю. Дату начала периода сохраню - двух байт для расчета хватит за глаза.

Спасибо: 0 
ПрофильЦитата Ответить





Пост N: 439
Зарегистрирован: 08.07.06
ссылка на сообщение  Отправлено: 04.04.15 18:08. Заголовок: alkresin пишет: Cdx..


alkresin пишет:

 цитата:
Cdx по определению еще со времен Клиппера - компактный индекс. Впрочем, можете проверить сами. Я вот сейчас построил для сравнения индексы к одной своей таблице:

Кол-во записей - 344600
Длина ключа - 14 байт
Размер cdx индекса - 1679K
Размер ntx индекса - 8617K



14 байт * 344600 записей = 4'824'400 байт. Что-то не сходится...
В любом случае - потестирую CDX



Спасибо: 0 
ПрофильЦитата Ответить





Пост N: 440
Зарегистрирован: 08.07.06
ссылка на сообщение  Отправлено: 04.04.15 18:11. Заголовок: petr707 пишет: А ка..


petr707 пишет:

 цитата:
А как и когда заполнить ? Однократно по требованию(отдела закупщиков) или держать постоянно готовым, а модифицировать сразу по факту каждой продажи - это пополнение отчета.
Упрощенно - факт продажи заносится в базу продаж. Если нужно узнать итоговую сумму продаж за день на текущий момент ,
создается отчет типа SUM... или TOTAL.. или Dbeval . Получаем SUMDAY
Вариант оперативного агрегата - открыто две таблицы - продаж и таблица итога(агрегат). По факту продаж дополнительно к записи в первую таблицу , сумма каждой продажи добавляется к SUMDAY во второй таблице в момент продажи.
Иногда морока с обслуживанием второй таблицы(готовый отчет) не стоит свеч. Быстрее и проще по каждому запросу(или по расписанию) заново сделать SUM.. или TOTAL..



Планируется раз в неделю пересоздавать полностью, например, за последние 2 года. Далее, каждый день, в 4 утра проводится тех.обслуживание - пересоздание индексов, подчистка мусора, упаковка и тп. В это время думаю делать обновление "агрегата" за, скажем 14 дней. Актуальность изменений в течении рабочего дня не очень важна.

Спасибо: 0 
ПрофильЦитата Ответить





Пост N: 78
Зарегистрирован: 13.06.12
ссылка на сообщение  Отправлено: 04.04.15 18:13. Заголовок: Со временем таблица ..


Со временем таблица опять увеличится. Не лучше ли, не меняя уже готовой структуры, переносить даныые старше 2-3 лет в архив, а в таблице оставлять только актуальные данные? Это можно делать в начале каждого года, занося в таблицу остатки на 1 яваря. Возможно, тогда вас устроит и уже существующий индекс.

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник


Пост N: 1043
Зарегистрирован: 27.01.07
ссылка на сообщение  Отправлено: 04.04.15 19:06. Заголовок: Sergy пишет: 14 бай..


Sergy пишет:

 цитата:
14 байт * 344600 записей = 4'824'400 байт. Что-то не сходится...


Вот поэтому он и называется "компактным" ))

Спасибо: 0 
ПрофильЦитата Ответить





Пост N: 441
Зарегистрирован: 08.07.06
ссылка на сообщение  Отправлено: 04.04.15 19:23. Заголовок: PSP пишет: Вот поэт..


PSP пишет:

 цитата:
Вот поэтому он и называется "компактным" ))


Разобрался. Если он "компактный" на диске - это не значит, что он "компактный" в памяти: https://groups.google.com/forum/#!starred/harbour-users/vDXzEB_Ih8I

 цитата:
druzus:
CDX format allows to create 4 different types of indexes:
1. single tag noncompressed indexes (def.ext: .idx)
2. single tag compressed indexes (def.ext: .idx)
3. multi tag non-compressed indexes (def.ext: .cdx)
4. multi tag compressed indexes (def.ext: .cdx)

Harbour and CL53 DBFCDX (COMIX) support only 4-th format.



Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник


Пост N: 1044
Зарегистрирован: 27.01.07
ссылка на сообщение  Отправлено: 04.04.15 19:49. Заголовок: Sergy пишет: Если о..


Sergy пишет:

 цитата:
Если он "компактный" на диске - это не значит, что он "компактный" в памяти


И что? Он работает. У меня есть таблицы весом около 200Mb (добавлено: записей около 900000). На размер индекса я не смотрел. Работает с такой же скоростью, как и когда таблицы были пустыми. Надо логику менять. Размер в нынешних условиях не имеет значения.

Спасибо: 0 
ПрофильЦитата Ответить
администратор




Пост N: 4659
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 04.04.15 19:51. Заголовок: Sergy пишет: Разобр..


Sergy пишет:

 цитата:
Разобрался. Если он "компактный" на диске - это не значит, что он "компактный" в памяти


Намекаешь что NTX vs CDX это примерно тоже что EXE vs EXE пожатый UPX ?
Тут тестить надо на самом деле.
У меня размер одной базы 250 метров , индексы IDX , работает в сети и примерно 25 юзеров ,
на тормоза ни кто не жалуется. Кол-во записей ~ чуть больше 2 лимонов.

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 548
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 04.04.15 20:41. Заголовок: SergKis пишет:str(cr..


SergKis пишет:
 цитата:
str(crc32(cKey), 8) или str(crc16(cKey, 5)


немного наврал (по памяти), нашел у себя место где применял. надо:
str(hb_crc32(cKey), 10) или str(hb_crc16(cKey, 5)
использовал в похожей ситуации: запись в инд.поле
KY := str(hb_crc32(R_6+R_7+R_2+Dtos(R_4)+R_13+str(R_46)),10)
это код, склад, операция, дата, докум., id

Спасибо: 0 
ПрофильЦитата Ответить





Пост N: 443
Зарегистрирован: 08.07.06
ссылка на сообщение  Отправлено: 08.04.15 22:56. Заголовок: Dima пишет: Намекае..


Dima пишет:

 цитата:
Намекаешь что NTX vs CDX это примерно тоже что EXE vs EXE пожатый UPX ?
Тут тестить надо на самом деле.


Przemek пишет, что "не все так однозначно": _https://groups.google.com/forum/#!topic/harbour-users/EB-eDbnEDMA
Различия во внутренней структуре индекса есть.
Но DBFNTX можно заставить работать по аналогии с CDX. Будет время - потестю.


 цитата:

У меня размер одной базы 250 метров , индексы IDX , работает в сети и примерно 25 юзеров ,
на тормоза ни кто не жалуется. Кол-во записей ~ чуть больше 2 лимонов.


У меня аналогично, рабочая таблица продаж, под 100..200 мегов - никто не жалуется. Интенсивность разная. Во время работы юзера прошла выборка по индексу, десяток-другой записей - мгновение и ждем реакции пользователя... Во время активного заполнения справочника с активным поиском по таблице с ~5 млн значений ощущаются тормоза.

Пример: прогресс дошел до середины за минуту, таблица разрослась до 100 мегов. Еще две минуты она доходит до 75%. Еще через три - до 100%. Итоговый размер - под 200 мег.
Итого получается, что работа с первой сотней мегов прошла за минуту, со второй - за пять. Итого шесть минут.

Но нужно будет потестить с CDX.

Спасибо: 0 
ПрофильЦитата Ответить
Ответов - 24 , стр: 1 2 All [только новые]
Ответ:
1 2 3 4 5 6 7 8 9
большой шрифт малый шрифт надстрочный подстрочный заголовок большой заголовок видео с youtube.com картинка из интернета картинка с компьютера ссылка файл с компьютера русская клавиатура транслитератор  цитата  кавычки моноширинный шрифт моноширинный шрифт горизонтальная линия отступ точка LI бегущая строка оффтопик свернутый текст

показывать это сообщение только модераторам
не делать ссылки активными
Имя, пароль:      зарегистрироваться    
Тему читают:
- участник сейчас на форуме
- участник вне форума
Все даты в формате GMT  3 час. Хитов сегодня: 556
Права: смайлы да, картинки да, шрифты да, голосования нет
аватары да, автозамена ссылок вкл, премодерация откл, правка нет