Хранение массива целых чисел
От: merge  
Дата: 01.04.24 07:05
Оценка:
Есть такой массив чисел. кол-во продаж по дням недели за некоторый период.
Надо это хранить в базе занимая как можно меньше места. Период в среднем может быть 30 дней. Получается будет порядка 100 байт в среднем.
Пока вот первое что в голове есть — через тире.
Думал над генерацией хэша еще. У кого какие мысли

1-4-5-63-2-43-23-31-123-343-312-5646-12-42-4533-1123-552
Re: Хранение массива целых чисел
От: Буравчик Россия  
Дата: 01.04.24 07:22
Оценка: 2 (1)
Здравствуйте, merge, Вы писали:

M>Надо это хранить в базе занимая как можно меньше места. Период в среднем может быть 30 дней. Получается будет порядка 100 байт в среднем.

M>Пока вот первое что в голове есть — через тире.

Можно так и хранить как байты, можно как base64.
Могут быть проблемы с little-big-endian, но вряд ли это актуально.
Best regards, Буравчик
Re: Хранение массива целых чисел
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 01.04.24 07:36
Оценка:
Здравствуйте, merge, Вы писали:

M>1-4-5-63-2-43-23-31-123-343-312-5646-12-42-4533-1123-552


Можно использовать unsigned int16, у тебя явно не больше 32 тысяч продаж. Если этого не хватает, то хранить не абсолютные значения, а дельты.
Re: Хранение массива целых чисел
От: cppguard  
Дата: 01.04.24 07:48
Оценка:
Здравствуйте, merge, Вы писали:

M>Надо это хранить в базе занимая как можно меньше места.

M>Пока вот первое что в голове есть — через тире.


Такие задачи очень сильно зависят от последующих режимов чтения. Если не оглядываться на них, то нужно хранить в двоичном формате дельты и сжимать gzip. Получится очень близко к эффективному размеру информации, ниже которого сжимать можно только с потерями.
Re[2]: Хранение массива целых чисел
От: Mihas  
Дата: 01.04.24 08:23
Оценка:
Здравствуйте, Nuzhny, Вы писали:

N>Можно использовать unsigned int16, у тебя явно не больше 32 тысяч продаж.

64к же)
Re[2]: Хранение массива целых чисел
От: merge  
Дата: 01.04.24 08:38
Оценка:
Здравствуйте, Nuzhny, Вы писали:

N>Здравствуйте, merge, Вы писали:


M>>1-4-5-63-2-43-23-31-123-343-312-5646-12-42-4533-1123-552


N>Можно использовать unsigned int16, у тебя явно не больше 32 тысяч продаж. Если этого не хватает, то хранить не абсолютные значения, а дельты.


я плохо объяснил. массив целых чисел надо эффективно хранить в базе. Пока вариант рассматривал только строкой в виде 1-4-5-63-2-43-23-31-123-343-312-5646-12-42-4533-1123-552
на бэке, да, unsigned int16 эффективней int будет.
или я не понял мысль)
Re[3]: Хранение массива целых чисел
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 01.04.24 08:42
Оценка:
Здравствуйте, merge, Вы писали:

M>я плохо объяснил. массив целых чисел надо эффективно хранить в базе. Пока вариант рассматривал только строкой в виде 1-4-5-63-2-43-23-31-123-343-312-5646-12-42-4533-1123-552

M>на бэке, да, unsigned int16 эффективней int будет.
M>или я не понял мысль)

В базе — это обязательно строка? Вот твоя строка по байту на символ занимает 56 байт. Если хранить эти 17 значений каждое как uint16, то будет 34 байта. Это же маленькие blob, нет?
Re[4]: Хранение массива целых чисел
От: merge  
Дата: 01.04.24 09:02
Оценка:
Здравствуйте, Nuzhny, Вы писали:

N>Здравствуйте, merge, Вы писали:


M>>я плохо объяснил. массив целых чисел надо эффективно хранить в базе. Пока вариант рассматривал только строкой в виде 1-4-5-63-2-43-23-31-123-343-312-5646-12-42-4533-1123-552

M>>на бэке, да, unsigned int16 эффективней int будет.
M>>или я не понял мысль)

N>В базе — это обязательно строка? Вот твоя строка по байту на символ занимает 56 байт. Если хранить эти 17 значений каждое как uint16, то будет 34 байта. Это же маленькие blob, нет?


необязательно строка. а, понял мысль. ты предлагаешь одно поле blob сделать и в нем хранить unsigned int16 массив по сути?
Re: Хранение массива целых чисел
От: _FRED_ Черногория
Дата: 01.04.24 09:32
Оценка:
Здравствуйте, merge, Вы писали:

M>Есть такой массив чисел. кол-во продаж по дням недели за некоторый период.

M>1-4-5-63-2-43-23-31-123-343-312-5646-12-42-4533-1123-552

В строке выше 17 значений. Как это связано с днями недели? Может имелись в виду дни месяца (для каждого месяца хранить количество продаж за каждый день)?
Help will always be given at Hogwarts to those who ask for it.
Re[5]: Хранение массива целых чисел
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 01.04.24 10:02
Оценка: 2 (1)
Здравствуйте, merge, Вы писали:

M>необязательно строка. а, понял мысль. ты предлагаешь одно поле blob сделать и в нем хранить unsigned int16 массив по сути?


Да
Re[2]: Хранение массива целых чисел
От: merge  
Дата: 02.04.24 17:37
Оценка: +1
Здравствуйте, cppguard, Вы писали:

C>Здравствуйте, merge, Вы писали:


M>>Надо это хранить в базе занимая как можно меньше места.

M>>Пока вот первое что в голове есть — через тире.
C>

C>Такие задачи очень сильно зависят от последующих режимов чтения. Если не оглядываться на них, то нужно хранить в двоичном формате дельты и сжимать gzip. Получится очень близко к эффективному размеру информации, ниже которого сжимать можно только с потерями.


я про такое слышал, но реализацией не занимался.
можно примером пояснить?
к примеру такие данные есть: 5 — 8 — 4 — 12 в дельте будут как и как потом храним в двоичном виде?

а сжатие оно имеет тут смысл если строка редко будет больше 100 байт? а то мне кажется сжатие\расжатие не очень быстрая операция и есть смысл на больших размерах данных
Re[2]: Хранение массива целых чисел
От: merge  
Дата: 02.04.24 17:38
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, merge, Вы писали:


M>>Есть такой массив чисел. кол-во продаж по дням недели за некоторый период.

M>>1-4-5-63-2-43-23-31-123-343-312-5646-12-42-4533-1123-552

_FR>В строке выше 17 значений. Как это связано с днями недели? Может имелись в виду дни месяца (для каждого месяца хранить количество продаж за каждый день)?


да, ошибься. месяца. есть период в двух других полях и есть 2 поля: в одном храним по дням за весь период, во втором по неделям на этот же период
Re[3]: Хранение массива целых чисел
От: _FRED_ Черногория
Дата: 02.04.24 22:36
Оценка:
Здравствуйте, merge, Вы писали:

M>>>Есть такой массив чисел. кол-во продаж по дням недели за некоторый период.

M>>>1-4-5-63-2-43-23-31-123-343-312-5646-12-42-4533-1123-552

_FR>>В строке выше 17 значений. Как это связано с днями недели? Может имелись в виду дни месяца (для каждого месяца хранить количество продаж за каждый день)?

M>да, ошибься. месяца. есть период в двух других полях и есть 2 поля: в одном храним по дням за весь период, во втором по неделям на этот же период

Известно, на сколько большими могут быть числа? Если нормализация данных (в каждой строке хранить дату и количество продаж) по какой-то причине не подходит и нужно всё в строке, да и место сэкономить, то можно поработать над уменьшением длины строки.
Например, числа записывать не в десятичном формате, а в 52-ричном (английский алфавит с прописными и заглавными буквами) или даже ещё больше, набор символов можно выбрать произвольный.

Блоб, в котором просто массив целых (из подходящего числа битов), кажется (кто его знает, что у вас за база?), будет ещё экономнее (но, возможно, менее удобно). Чтобы как-то оптимизировать дальше размер этого блоба (если требуется) нужно что-то знать дополнительное об этих числах.
Help will always be given at Hogwarts to those who ask for it.
Re[4]: Хранение массива целых чисел
От: merge  
Дата: 03.04.24 06:25
Оценка:
Здравствуйте, _FRED_, Вы писали:



_FR>Известно, на сколько большими могут быть числа? Если нормализация данных (в каждой строке хранить дату и количество продаж) по какой-то причине не подходит и нужно всё в строке, да и место сэкономить, то можно поработать над уменьшением длины строки.


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

_FR>Например, числа записывать не в десятичном формате, а в 52-ричном (английский алфавит с прописными и заглавными буквами) или даже ещё больше, набор символов можно выбрать произвольный.


а есть готовые алгоритмы или либы для этого?

_FR>Блоб, в котором просто массив целых (из подходящего числа битов), кажется (кто его знает, что у вас за база?), будет ещё экономнее (но, возможно, менее удобно). Чтобы как-то оптимизировать дальше размер этого блоба (если требуется) нужно что-то знать дополнительное об этих числах.


база мсскл — 19. ну получается, что 52 ричный формат или блоб уже особой разницы не играют, всё равно придется конвертер писать на бэке до\перед вставкой?
на бэке работа идёт с линейный списком, то есть 10 дней будет как 10 элементов массива, просто в базе будет 1 строка и продажи будут в одном поле
Re: Хранение массива целых чисел
От: vsb Казахстан  
Дата: 03.04.24 07:22
Оценка:
Тип столбца — bytes.

Число хранится в переменном числе байтов, можно посмотреть в UTF-8 как сделано, в принципе вариантов много.

Сначала хранится абсолютное значение за 1 число, все последующие числа это разность между предыдущим и текущим. Т.е. если продажи 120, 105, 110, то хранятся числа 120, -15, +5.

Альтернативный подход: сначала просто записать числа как есть, можно в 4-байтовом формате, без выпендрёжа, в общем, а потом прогнать через какой-нибудь библиотечный gzip.

Думаю, будет плюс-минус одно и то же.

Ну или готовиться к хардкорному познанию алгоритмов сжатия и адаптации под конкретный случай, но это уже сложно.
Отредактировано 03.04.2024 7:24 vsb . Предыдущая версия .
Re[2]: Хранение массива целых чисел
От: _FRED_ Черногория
Дата: 03.04.24 09:29
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Сначала хранится абсолютное значение за 1 число, все последующие числа это разность между предыдущим и текущим. Т.е. если продажи 120, 105, 110, то хранятся числа 120, -15, +5.


А что может дать хранение дельты по сравнению с хранением абсолютного значения?
Help will always be given at Hogwarts to those who ask for it.
Re[3]: Хранение массива целых чисел
От: rudzuk  
Дата: 03.04.24 12:35
Оценка:
Здравствуйте, _FRED_, Вы писали:

FRE> А что может дать хранение дельты по сравнению с хранением абсолютного значения?


Да ничего, скорее всего, не даст. Тут и так-то размер данных крошечный: даже если отвести 4 байта на количество продаж, то для 31 дня нужно хранить всего 124 байта. Если это сжимать, то точно не gzip т.к. он прибавит минимум 22 байта к сжатым данным. Если заполнить такой массив значениям от 1 до 31 (три байта остаются нулевыми) то deflate с дефолтным уровнем сжатия его сожмет до 54 байт. Отрицательные дельты вполне могут привести к ухудшению сжатия, да еще и усожнят получение значений на конкретный день месяца. Тут, скорее, нужно просто определиться с требуемым количеством байтов, чтобы число продаж уместилось, и не страдать фигней.
avalon/3.0.2
Re[4]: Хранение массива целых чисел
От: merge  
Дата: 03.04.24 12:49
Оценка:
Здравствуйте, rudzuk, Вы писали:

R>Здравствуйте, _FRED_, Вы писали:


FRE>> А что может дать хранение дельты по сравнению с хранением абсолютного значения?


R>Да ничего, скорее всего, не даст. Тут и так-то размер данных крошечный: даже если отвести 4 байта на количество продаж, то для 31 дня нужно хранить всего 124 байта. Если это сжимать, то точно не gzip т.к. он прибавит минимум 22 байта к сжатым данным. Если заполнить такой массив значениям от 1 до 31 (три байта остаются нулевыми) то deflate с дефолтным уровнем сжатия его сожмет до 54 байт. Отрицательные дельты вполне могут привести к ухудшению сжатия, да еще и усожнят получение значений на конкретный день месяца. Тут, скорее, нужно просто определиться с требуемым количеством байтов, чтобы число продаж уместилось, и не страдать фигней.


оказалось, что может быть и годовые продажи, нечасто, но может. Квартал достаточно часто. так что получается 150 * 4 = 600 байт. это меняет что-то?
Re[5]: Хранение массива целых чисел
От: rudzuk  
Дата: 03.04.24 13:20
Оценка:
Здравствуйте, merge, Вы писали:

m> оказалось, что может быть и годовые продажи, нечасто, но может. Квартал достаточно часто. так что получается 150 * 4 = 600 байт. это меняет что-то?


Массив чытерыхбайтовых целых заполненный значениями от 1 до 150 deflate сжимает до 238 байт.
avalon/3.0.2
Re[5]: Хранение массива целых чисел
От: _FRED_ Черногория
Дата: 03.04.24 14:01
Оценка:
Здравствуйте, merge, Вы писали:

M>оказалось, что может быть и годовые продажи, нечасто, но может. Квартал достаточно часто. так что получается 150 * 4 = 600 байт. это меняет что-то?


А вам эти данные, внутренности, нужно когда-либо обновлять? Например, в строке данных за месяц исправить несколько каких-то значений?
Help will always be given at Hogwarts to those who ask for it.
Re[6]: Хранение массива целых чисел
От: merge  
Дата: 03.04.24 15:13
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, merge, Вы писали:


M>>оказалось, что может быть и годовые продажи, нечасто, но может. Квартал достаточно часто. так что получается 150 * 4 = 600 байт. это меняет что-то?


_FR>А вам эти данные, внутренности, нужно когда-либо обновлять? Например, в строке данных за месяц исправить несколько каких-то значений?


нет. они один раз расчитываются и дальше только на чтение. Единственное, что нужно будет в линейный массив потом разложить это при считывании в энтити по дням
Re[6]: Хранение массива целых чисел
От: rudzuk  
Дата: 03.04.24 15:15
Оценка:
Здравствуйте, rudzuk, Вы писали:

r> m> оказалось, что может быть и годовые продажи, нечасто, но может. Квартал достаточно часто. так что получается 150 * 4 = 600 байт. это меняет что-то?


r> Массив чытерыхбайтовых целых заполненный значениями от 1 до 150 deflate сжимает до 238 байт.


Попробовал еще вариант с формированием строки чисел с разделителем. Рандомно сгенерировал числа от 10 до 2000. Сжимается лучше чем сырой массив (размер сырого массива/сжатого массива/сжатой строки с разделителями): 124/97/48, 600/376/217. В таком варианте кодирование с дельтами может еще сократить размер.
avalon/3.0.2
Re[7]: Хранение массива целых чисел
От: rudzuk  
Дата: 03.04.24 15:27
Оценка:
Здравствуйте, rudzuk, Вы писали:

r> Попробовал еще вариант с формированием строки чисел с разделителем. Рандомно сгенерировал числа от 10 до 2000. Сжимается лучше чем сырой массив (размер сырого массива/сжатого массива/сжатой строки с разделителями): 124/97/48, 600/376/217. В таком варианте кодирование с дельтами может еще сократить размер.


Блин, лажанулся с цифрами. На самом деле они хуже. Вообще, часто получается, что длина строки выходит меньше чем сжатый сырой масссив, а сжатие строки не всегда приводит к уменьшению размера (на месячном диапазоне строка всегда получается короче, но это на равномерно распределенном рандоме). В общем, нужно на реальных данных экспериментировать.
avalon/3.0.2
Re[3]: Хранение массива целых чисел
От: vsb Казахстан  
Дата: 03.04.24 15:37
Оценка:
Здравствуйте, _FRED_, Вы писали:

vsb>>Сначала хранится абсолютное значение за 1 число, все последующие числа это разность между предыдущим и текущим. Т.е. если продажи 120, 105, 110, то хранятся числа 120, -15, +5.


_FR>А что может дать хранение дельты по сравнению с хранением абсолютного значения?


Если мы кодируем числа в кодировке с переменным числом битов, то чем меньше число, тем меньше битов нужно для его кодирования.
Re[4]: Хранение массива целых чисел
От: _FRED_ Черногория
Дата: 03.04.24 16:36
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>>>Сначала хранится абсолютное значение за 1 число, все последующие числа это разность между предыдущим и текущим. Т.е. если продажи 120, 105, 110, то хранятся числа 120, -15, +5.

_FR>>А что может дать хранение дельты по сравнению с хранением абсолютного значения?

vsb>Если мы кодируем числа в кодировке с переменным числом битов, то чем меньше число, тем меньше битов нужно для его кодирования.


А почему число будет меньше? В семпловой строке в стартовом сообщении разброс очень даже приличный:

1-4-5-63-2-43-23-31-123-343-312-5646-12-42-4533-1123-552

Может я не понимаю чего-то?

Если бы все числа были бы порядка нескольких тыщ, то я вижу выгоду от хранения небольшой дельты вместо большого абсолюта. А будет ли польза дельты если каждое число, допустим, случайно? Можно пример?
Help will always be given at Hogwarts to those who ask for it.
Re[5]: Хранение массива целых чисел
От: _FRED_ Черногория
Дата: 03.04.24 17:02
Оценка: 2 (1)
Здравствуйте, merge, Вы писали:

_FR>>Например, числа записывать не в десятичном формате, а в 52-ричном (английский алфавит с прописными и заглавными буквами) или даже ещё больше, набор символов можно выбрать произвольный.

M>а есть готовые алгоритмы или либы для этого?

Да это школьная задачка:
internal static class NumberFormatter
{
  // 64-base alphabet: 10 digits, lower and upper letters (2x26), and @, and #
  private const string Characters = "0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ#abcdefghijklmnopqrstuvwxyz";

  private static readonly int Base = Characters.Length;
  private static readonly double LogBase = Math.Log(Base);

  private static readonly Encoding ThisEncoding = Encoding.ASCII;
  private static readonly byte[] ByteArray = ThisEncoding.GetBytes(Characters);
  private static readonly string[] StringsArray = Array.ConvertAll(Characters.ToArray(), ch => ch.ToString());

  private const int StackAllocLimit = 22; // 22 symbols in enough to represent UInt128.MaxValue with base 64

  public static string ToString<T>(T number) where T : IBinaryInteger<T>, IMinMaxValue<T> {
    var typedBase = T.CreateChecked(Base);
    if(number < typedBase) {
      var index = Int32.CreateChecked(number);
      return StringsArray[index];
    }//if

    var bufferArray = default(byte[]); // For huge numbers ;o)
    var length = GetResultLength(number);
    var buffer = length <= StackAllocLimit ? stackalloc byte[length] : (bufferArray = ArrayPool<byte>.Shared.Rent(length));
    try {
      var index = length - 1; // Populating the buffer from the last symbol to the first
      while(number > T.Zero) {
        (number, var modulo) = T.DivRem(number, typedBase);
        var characterIndex = Int32.CreateChecked(modulo);

        Debug.Assert(index >= 0, $"index {{{index}}} < 0");
        buffer[index] = ByteArray[characterIndex];
        index--;
      }//while

      return ThisEncoding.GetString(buffer);
    } finally {
      if(bufferArray is not null) {
        ArrayPool<byte>.Shared.Return(bufferArray, clearArray: true /* To be sure :o) Can be omitted in a trusted environment */);
      }//if
    }//try

    static int GetResultLength(T number) {
      var value = number < T.MaxValue ? number + T.One : number;
      var doubleValue = Double.CreateChecked(value);
      return (int)Math.Ceiling(Math.Log(doubleValue) / LogBase);
    }
  }
}
Help will always be given at Hogwarts to those who ask for it.
Отредактировано 03.04.2024 17:08 _FRED_ (Истправил опечатку в имени идентификатора) . Предыдущая версия .
Re[5]: Хранение массива целых чисел
От: vsb Казахстан  
Дата: 04.04.24 02:53
Оценка: +1
Здравствуйте, _FRED_, Вы писали:

_FR>А почему число будет меньше? В семпловой строке в стартовом сообщении разброс очень даже приличный:

_FR>

_FR>1-4-5-63-2-43-23-31-123-343-312-5646-12-42-4533-1123-552

_FR>Может я не понимаю чего-то?

Обычно в подобных ситуациях — меньше. А так — надо мерять.

_FR>Если бы все числа были бы порядка нескольких тыщ, то я вижу выгоду от хранения небольшой дельты вместо большого абсолюта. А будет ли польза дельты если каждое число, допустим, случайно? Можно пример?


Если каждое число случайно, конечно никакого выигрыша не будет. Это попытка найти некоторую закономерность и сжать данные за счёт этого.
Re[7]: Хранение массива целых чисел
От: _FRED_ Черногория
Дата: 04.04.24 06:34
Оценка:
Здравствуйте, merge, Вы писали:

M>>>оказалось, что может быть и годовые продажи, нечасто, но может. Квартал достаточно часто. так что получается 150 * 4 = 600 байт. это меняет что-то?

_FR>>А вам эти данные, внутренности, нужно когда-либо обновлять? Например, в строке данных за месяц исправить несколько каких-то значений?

M>нет. они один раз расчитываются и дальше только на чтение. Единственное, что нужно будет в линейный массив потом разложить это при считывании в энтити по дням


Если на эти данные никому не нужно смотреть "глазами" прям в БД, я б хранил просто два-три-четыре (смотря какое максимальное значение ожидается) байта на каждый номер последовательно. Если считать, что числа эти случайные, то сжатие не сильно поможет. Кодированипе-декодирование будет не сложным и быстрым.
Help will always be given at Hogwarts to those who ask for it.
Re[6]: Хранение массива целых чисел
От: _FRED_ Черногория
Дата: 04.04.24 06:40
Оценка:
Здравствуйте, vsb, Вы писали:

_FR>>А почему число будет меньше? В семпловой строке в стартовом сообщении разброс очень даже приличный:

_FR>>Может я не понимаю чего-то?
vsb>Обычно в подобных ситуациях — меньше. А так — надо мерять.

_FR>>Если бы все числа были бы порядка нескольких тыщ, то я вижу выгоду от хранения небольшой дельты вместо большого абсолюта. А будет ли польза дельты если каждое число, допустим, случайно? Можно пример?

vsb>Если каждое число случайно, конечно никакого выигрыша не будет. Это попытка найти некоторую закономерность и сжать данные за счёт этого.

Спасибо. Правильно я понимаю, что в таком разе с каждой дельтой нужно будет ещё и хранить и размер этой дельты или полагаться, что она всегда не болшьше некоторого значения (если мы не говорим о представлении данных в виде строки)?
Например, если абсолютное значение — четырёхбайтовое то дельта двух- или даже одно- байтовая и экономия за счёт этого?

Просто всё ещё кажется, что просто хранить данные в бинарном виде фиксированного размера "одно за другим" будет значительно экономнее.
Help will always be given at Hogwarts to those who ask for it.
Re[7]: Хранение массива целых чисел
От: vsb Казахстан  
Дата: 04.04.24 13:58
Оценка: 20 (1) +2
Здравствуйте, _FRED_, Вы писали:

_FR>Спасибо. Правильно я понимаю, что в таком разе с каждой дельтой нужно будет ещё и хранить и размер этой дельты или полагаться, что она всегда не болшьше некоторого значения (если мы не говорим о представлении данных в виде строки)?

_FR>Например, если абсолютное значение — четырёхбайтовое то дельта двух- или даже одно- байтовая и экономия за счёт этого?

Нужно использовать какую-нибудь схему кодирования с переменной длиной. Простой пример:

Число от 0 до 2^7 — 1 хранится в одном байте со старшим нулевым битом.
Число от 0 до 2^14 — 1 хранится в двух байтах, в первом байте старший бит единица и 7 битов на число, во втором байте старший бит ноль и 7 битов на число. В итоге на число уходит 14 битов и 2 служебных бита.
Число от 0 до 2^21 — 1 хранится в трёх байтах, в первом байте старший бит единица и 7 битов на число, во втором байте старший бит единица и 7 битов на число, в третьем байте старший бит ноль и 7 битов на число. В итоге на число уходит 21 бит и три служебных бита.

Тут идут пересечения по первому диапазону, поэтому можно чуть лучше сделать, это не суть.

Это один из примеров, можно и другие примеры кодировки придумать.

_FR>Просто всё ещё кажется, что просто хранить данные в бинарном виде фиксированного размера "одно за другим" будет значительно экономнее.


Надо считать на конкретных данных. Большого проигрыша тут быть не должно.
Отредактировано 04.04.2024 13:59 vsb . Предыдущая версия .
Re: Хранение массива целых чисел
От: Teolog  
Дата: 04.04.24 19:24
Оценка:
Для хранения — blob protobuf содержащий в обьект с repeated(на случай если захочется запихнуть еще что-нибудь)
Дополнительно для оптимизации хранить не абсолютное значение, а разницу с предидущим днем для всех кроме первого.
тут может выйти и хуже и лучше — и не факт что стоит возни
Re: Хранение массива целых чисел
От: Sharowarsheg  
Дата: 04.04.24 19:32
Оценка:
Здравствуйте, merge, Вы писали:

M>Есть такой массив чисел. кол-во продаж по дням недели за некоторый период.

M>Надо это хранить в базе занимая как можно меньше места.

А сколько их вообще у тебя?
Re: Хранение массива целых чисел
От: diez_p  
Дата: 05.04.24 10:38
Оценка: +2
Здравствуйте, merge, Вы писали:

M>Есть такой массив чисел. кол-во продаж по дням недели за некоторый период.

M>Надо это хранить в базе занимая как можно меньше места. Период в среднем может быть 30 дней. Получается будет порядка 100 байт в среднем.
M>Пока вот первое что в голове есть — через тире.
M>Думал над генерацией хэша еще. У кого какие мысли

M>1-4-5-63-2-43-23-31-123-343-312-5646-12-42-4533-1123-552



Тут все советуют как хранить, но кто читать эти данные будет?
точно нужна экономия диска, вроде данных то на копейки.
не проще ли выранивать по 2/4 байта, и потом с базы лить блобы ? там же и кеши и оптимизации и все что хочешь. надо ли читать данные в какой-то конкретный день или читается все сразу за неделю?
конечно продажи скорее всего читают линейно и можно вообще уложить год в один массив.
366*32=~10кб
10 лет — 100кб на позицию
1млн позиций 100 гб такое даже в ОЗУ влезет
Отредактировано 05.04.2024 10:41 diez_p . Предыдущая версия .
Re[3]: Хранение массива целых чисел
От: cppguard  
Дата: 08.04.24 05:14
Оценка:
Здравствуйте, merge, Вы писали:

M>к примеру такие данные есть: 5 — 8 — 4 — 12 в дельте будут как и как потом храним в двоичном виде?

Реализации могут быть разные. Можно дельты сделать того же размера, что и опорное значение, тогда выгода будет только вместе с использованеим сжатия. Можно дельту сделать размером в 1 байт, но тогда значения, очевидно, должны попадать в 0..255. Ещё вместо разницы можно считать xor, тогда алгоритм будет работать и с вещественными числами. Одним словом — простор для фантазии.

M>а сжатие оно имеет тут смысл если строка редко будет больше 100 байт? а то мне кажется сжатие\расжатие не очень быстрая операция и есть смысл на больших размерах данных

Если строка меньше 100 байт, зачем вообще что-то сжимать?
Re[3]: Хранение массива целых чисел
От: Sinclair Россия https://github.com/evilguest/
Дата: 18.04.24 15:39
Оценка: 20 (1)
Здравствуйте, _FRED_, Вы писали:
_FR>А что может дать хранение дельты по сравнению с хранением абсолютного значения?
То, что маленькие дельты будут встречаться чаще больших. Это позволит применить схему неравномерного кодирования, и сократить общую длину.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Хранение массива целых чисел
От: swame  
Дата: 22.04.24 18:12
Оценка:
Здравствуйте, merge, Вы писали:

M>Есть такой массив чисел. кол-во продаж по дням недели за некоторый период.

M>Надо это хранить в базе занимая как можно меньше места. Период в среднем может быть 30 дней. Получается будет порядка 100 байт в среднем.
M>Пока вот первое что в голове есть — через тире.
M>Думал над генерацией хэша еще. У кого какие мысли

M>1-4-5-63-2-43-23-31-123-343-312-5646-12-42-4533-1123-552



Я занимался компактным сохранением последовательность чисел в строку.
Есть разница между несортированными и сортированными массивами.
В твоем случае несортированный.

И для тех и для других использовал дельту между соседними значениями.
И алгоритмы VLQ (используется например в git ) и GVE (используется в protobuf).
VLQ использует минимум 1 байт на хранимое значение, а GVE 6 байт на 4 значения.
Но GVE более комфортный для процессора.

По теме
https://habr.com/ru/companies/badoo/articles/451938/
https://habr.com/ru/articles/511646/
https://www.programmersought.com/article/28225953711/
http://roaringbitmap.org/software/

В результате кодирования массив целых преобразуется в массив 32-битных целых, но меньшего объема памяти, храню их в строке.
Хранимая последовательность у меня выглядит так:

"groupeddata": "4F4F6C39 394F4F85 31974F85 394F8539 4F394F39 6439394F 876C3964 85316464 87648531 64266C4F 31648564 4F853997 85858585 854F856C 31313164 39854F4F 396C8539 85858539 8585394F 394F3985 3939644F 85398585 85858539 64398585 976C4F64 3939854F 8531396C 85858585 39393939 39393939 4F4F4F4F 4F4F4F4F 85856C4F 6C646485 4F39396C 31974F4F 39393985 4F979739 4F6C854F 8597974F 39393939 39646439 6C973985 854F3985 3997974F 85399785 64979785 974F9797 976C6C39 64856497 26266464 85853985 64393939 646C3964 9787976C
....
26262626 26262626 26262626 26262626 85262626 1B262685 2828281B 28281B28 28281B28 54541B28 28282854 1B282828 28282828 28282828 28282828 281B2854 64641B1B 31316464 64313131 31316464 64646431 31312626 64643131 31316464 31312626 85853939 64642626 64313164 4B643164 31856439 85313164 85858585 39313185 64646439 2685854F 31646426 85262631 4F973985 3131316C 31316431 26313131 64646426 64646464 64313164 26313164 85858526 8531314B 26262626 64643131 85363685 64646485 6464644B 31312626 31643131 64643164 26263131 26263131 28286854 1B1B2828 28535453 681B541B 54286828 28885428 2843541B 5468681B 1B888188 1B1B881B 28881B81 00438168",

Сортированный массив я анализировал на плотность встречающихся значений и разбивал на чейны 3 видов:
1. Range — идущие подряд n чисел начиная с M
2. Битмап — числа начиная с M кодируются битами, плотность 1 бит на число.
3. Разреженные массивы (дельта кодируется алгоритмами VLQ или GVE).
Все множество кодируется последовательностью таких чейнов, минимальный размер чейна 4 байта.
Отредактировано 22.04.2024 18:16 swame . Предыдущая версия . Еще …
Отредактировано 22.04.2024 18:15 swame . Предыдущая версия .
Отредактировано 22.04.2024 18:14 swame . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.