Автор | Сообщение |
|
| |
Пост 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 Спасибо.
|
|
|
Ответов - 24
, стр:
1
2
All
[только новые]
|
|
|
| постоянный участник
|
Пост N: 1042
Зарегистрирован: 27.01.07
|
|
Отправлено: 04.04.15 09:05. Заголовок: Чё-та я не врубился,..
Чё-та я не врубился, зачем такие сложности. dbfcdx не пробовал?
|
|
|
|
| |
Пост N: 4658
Зарегистрирован: 17.05.05
|
|
Отправлено: 04.04.15 09:07. Заголовок: PSP пишет: dbfcdx н..
PSP пишет: Да он где то писал , что по каким то причинам он не подходит. Задача локальная и можно было бы прикрутить локальный ADS и юзать индексы IDX.
|
|
|
|
| |
Пост N: 162
Зарегистрирован: 19.05.05
|
|
Отправлено: 04.04.15 09:52. Заголовок: У меня в некоторых з..
У меня в некоторых задачах построены индексы NTX по двоичному полю вроде все работает и нареканий не было
|
|
|
|
| moderator
|
Пост N: 895
Зарегистрирован: 06.07.06
|
|
Отправлено: 04.04.15 10:09. Заголовок: Dima пишет: Да он г..
Dima пишет: цитата: | Да он где то писал , что по каким то причинам он не подходит. |
| Нет и не может быть таких причин. Что до основного вопроса - можно попробовать изменить формат таблицы - заменить "интересные" типы данных на "C" - утрамбовать с помощью своих функций поля, входящие в индекс. Если размер становится критичным, стоит разбить таблицу на несколько, по годам - учитывая, что со временем она будет расти.
|
|
|
|
| |
Пост N: 126
Зарегистрирован: 21.04.13
|
|
Отправлено: 04.04.15 10:11. Заголовок: Т.е. нужно "бинарное" значение даты и 32-битного числа.
Не, не нужно. Полагаю, ложный путь. Не приведет к цели. Какая она- ускорение доступа ? Или экономия места на диске ? Возможно, проще изменить архитектуру - перепроектировать размещение данных в таблицах.. Таблица напоминает оперативно модифицируемый агрегатный отчет. Зачем держать данные за два года, меняется наверняка только последний текущий месяц? Возможно, быстрее и проще пересоздавать отчет целиком , чем поддерживать оперативный агрегат.
|
|
|
|
| постоянный участник
|
Пост N: 543
Зарегистрирован: 17.02.12
|
|
Отправлено: 04.04.15 10:11. Заголовок: Sergy надо избавить..
Sergy надо избавиться от вычисления ключа, добавив поле ключа и заполнять его в момент образования записи, дату можно сократить до год(2) и номер дня от начала года, + полученный ключ (символьный) можно пропустить через crc32 и в ключе использовать значение от crc32, но надо посмотреть точнее, может code+str(crc32(...), 8), но это писать в поле KY и индекс простой INDEX ON KY TO ...
|
|
|
|
| постоянный участник
|
Пост N: 544
Зарегистрирован: 17.02.12
|
|
Отправлено: 04.04.15 10:53. Заголовок: PS. Даже, доспустив ..
PS. Даже, доспустив дублирование ключа, можно поменять точный подвод, на относительный - подводим по ключу - do while ищем точное значение на совпадение по реальным значениям полей записи т.е. можно использовать и str(crc16(...), 5)
|
|
|
|
| |
Пост N: 437
Зарегистрирован: 08.07.06
|
|
Отправлено: 04.04.15 11:29. Заголовок: Отвечу по пооядку. ..
Отвечу по порядку. С планшета, поэтому без цитат, сорри. Почитал я реализацию dbfcdx/dbfntx в Harbour - по внутренней структуре/ограничениям между ними нет разницы. CDX лишь позволяет в одном файле хранить несколько тегов. IDX/ADS - ради одного, пусть "гигантского" отчета прикручивать? Дадут ли они реальное увеличение именно скорости поиска среди миллионов записей? Не уверен, потому что не пробовал. Для повседневной работы с запасом хватает dbfntx. DBFNTX у меня нормально работает с двоичными данными. В данном примере смешаны строка+дата+число Вариант с укороченным индексом - только, например, кода товара и последующим dowhile ... skip enddo - буду пробовать тоже. Может быть, он даст прирост скорости. Спасибо. По структуре данных - не очень понимаю, что такое "оперативно модифицируемый агрегатный расчет". Задача - заполнить таблицу товар/дата/остаток/продано за длительный период - на основании текущих остатков + журналов продаж/приходов/перемещений. Это нужно для анализа работы отдела закупщиков, более грамотного планирования пополнения складских запасов, выявления сезонности товара и тп. Да, обновляться на регулярной основе будут данные за последние дней 10-15, тк именно в них возможны корректировки. Но ведь эти данные еще нужно быстро найти и обновить в таблице, хранящей всю эту информацию. Разбивка на несколько таблиц по годам... Да, возможно придется пойти и по этому пути. Не хотелось-бы, тк реально анализировать более двух-трех лет вряд-ли кому понадобится. Добавление "индексного поля" - мне кажется, один из наиболее реальных способов... Идеально было-бы получить дату в виде строки размером в три байта (в которых она хранится). Но как ? Спасибо.
|
|
|
|
| |
Пост 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 Ну а число дней - паковать
|
|
|
|
| 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))
|
|
|
|
| постоянный участник
|
Пост N: 545
Зарегистрирован: 17.02.12
|
|
Отправлено: 04.04.15 12:15. Заголовок: Sergy пишет:получить..
Sergy пишет: цитата: | получить дату в виде строки размером в три байта |
| если использовать str(crc32(cKey), 8), то все равно, как получена дата - хоть словами, для данного примера (важно формировать cKey), для других индексов в других файлах alkresin прав
|
|
|
|
|
| постоянный участник
|
Пост 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 вам виднее по задаче
|
|
|
|
| постоянный участник
|
Пост N: 547
Зарегистрирован: 17.02.12
|
|
Отправлено: 04.04.15 12:56. Заголовок: alkresin пишет:Нет и..
alkresin пишет: цитата: | Нет и не может быть таких причин. |
| если у файла dbf только один индекс (и имя индекса совпадает с dbf), то преобразовать в cdx для начала только его - не должно быть проблеммой: REQUEST DBFCDX в открытие этого файла добавить VIA ... и уже все должно срастись по текстам
|
|
|
|
| |
Пост N: 128
Зарегистрирован: 21.04.13
|
|
Отправлено: 04.04.15 14:55. Заголовок: что такое "оперативно модифицируемый агрегатный расчет"
Задача - заполнить таблицу товар/дата/остаток/продано за длительный период - на основании текущих остатков + журналов продаж/приходов/перемещений. А как и когда заполнить ? Однократно по требованию(отдела закупщиков) или держать постоянно готовым, а модифицировать сразу по факту каждой продажи - это пополнение отчета. Упрощенно - факт продажи заносится в базу продаж. Если нужно узнать итоговую сумму продаж за день на текущий момент , создается отчет типа SUM... или TOTAL.. или Dbeval . Получаем SUMDAY Вариант оперативного агрегата - открыто две таблицы - продаж и таблица итога(агрегат). По факту продаж дополнительно к записи в первую таблицу , сумма каждой продажи добавляется к SUMDAY во второй таблице в момент продажи. Иногда морока с обслуживанием второй таблицы(готовый отчет) не стоит свеч. Быстрее и проще по каждому запросу(или по расписанию) заново сделать SUM.. или TOTAL..
|
|
|
|
| |
Пост 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 Ну а число дней - паковать |
| Да, наверное так и сделаю. Дату начала периода сохраню - двух байт для расчета хватит за глаза.
|
|
|
|
| |
Пост 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
|
|
|
|
| |
Пост N: 440
Зарегистрирован: 08.07.06
|
|
Отправлено: 04.04.15 18:11. Заголовок: petr707 пишет: А ка..
petr707 пишет: цитата: | А как и когда заполнить ? Однократно по требованию(отдела закупщиков) или держать постоянно готовым, а модифицировать сразу по факту каждой продажи - это пополнение отчета. Упрощенно - факт продажи заносится в базу продаж. Если нужно узнать итоговую сумму продаж за день на текущий момент , создается отчет типа SUM... или TOTAL.. или Dbeval . Получаем SUMDAY Вариант оперативного агрегата - открыто две таблицы - продаж и таблица итога(агрегат). По факту продаж дополнительно к записи в первую таблицу , сумма каждой продажи добавляется к SUMDAY во второй таблице в момент продажи. Иногда морока с обслуживанием второй таблицы(готовый отчет) не стоит свеч. Быстрее и проще по каждому запросу(или по расписанию) заново сделать SUM.. или TOTAL.. |
| Планируется раз в неделю пересоздавать полностью, например, за последние 2 года. Далее, каждый день, в 4 утра проводится тех.обслуживание - пересоздание индексов, подчистка мусора, упаковка и тп. В это время думаю делать обновление "агрегата" за, скажем 14 дней. Актуальность изменений в течении рабочего дня не очень важна.
|
|
|
|
| |
Пост N: 78
Зарегистрирован: 13.06.12
|
|
Отправлено: 04.04.15 18:13. Заголовок: Со временем таблица ..
Со временем таблица опять увеличится. Не лучше ли, не меняя уже готовой структуры, переносить даныые старше 2-3 лет в архив, а в таблице оставлять только актуальные данные? Это можно делать в начале каждого года, занося в таблицу остатки на 1 яваря. Возможно, тогда вас устроит и уже существующий индекс.
|
|
|
|
| постоянный участник
|
Пост N: 1043
Зарегистрирован: 27.01.07
|
|
Отправлено: 04.04.15 19:06. Заголовок: Sergy пишет: 14 бай..
Sergy пишет: цитата: | 14 байт * 344600 записей = 4'824'400 байт. Что-то не сходится... |
| Вот поэтому он и называется "компактным" ))
|
|
|
|
| |
Пост 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. |
|
|
|
|
Ответов - 24
, стр:
1
2
All
[только новые]
|
|