#c# #bigdata
Вопрос:
У меня есть много данных в следующей текстовой форме:
4c5c,6c4h,486,30
4c5c,6c5h,486,30
4c5c,6c6h,458,0
4c5c,6c7h,648,9
4c5c,6c8h,648,9
3sTs,QsKs,182,0
3sTs,QsAs,182,0
3sTs,KsAs,743,0
3sJs,4s5s,495,0
3sJs,4s6s,625,0
3sJs,4s7s,739,0
3sJs,4s8s,739,0
3sJs,4s9s,739,0
3sJs,4sTs,739,0
3sJs,4sQs,182,0
3sJs,4sKs,739,0
3sJs,4sAs,625,0
3sJs,5s6s,625,0
3sJs,5s7s,739,0
3sJs,5s8s,739,0
В каждой строке первые 2 термина представляют ключ, а вторые 2 термина представляют значения.
напр.
КЛЮЧ: 3sJs,5s8s
ЗНАЧЕНИЕ: 739,0
У меня более 14 миллиардов этих строк, и я храню их в словаре для быстрого доступа. Это проблематично, так как существует около 250 ГБ текстовых данных, которые требуют много памяти при хранении в словаре. Однако я заметил, что многие значения идентичны для нескольких ключей. Есть ли какой-то альтернативный способ словаря, в котором я могу хранить эти данные с меньшими требованиями к памяти, чтобы использовать тот факт, что многие значения повторяются? Я раньше не использовал базу данных с программой на C#, но немного поработал с postgres — является ли sqlite моим лучшим/единственным разумным вариантом и уменьшит ли он размер моего приложения до приемлемого размера для распространения?
Комментарии:
1. Являются ли эти текстовые данные статичными? Я сомневаюсь, что вы можете уменьшить размер, поместив его в базу данных sqlite. Могут ли быть определены какие-либо ограничения? Например, длина ключей, минимальное и максимальное значения.
2. Ключи-это игральные карты, например, 3s-это 3 пики. Данные никогда не изменятся. Значения не превышают 990.
3. Затем я бы поместил данные в 5-мерный массив шорт. первые 4 десятицентовика — это индекс карты (от 0 до 51-присвоите картам числовое значение), 5-е-значение 0 или 1. Это уменьшает ваши данные до прибл. 28 МБ. И это также самый быстрый способ получить к ним доступ с помощью ключей.
4. Кстати, я не играю в карты, поэтому не знаю, сколько там карт. Я предположил, что 52, выполнив поиск в Google. Если это так, то вы не можете иметь 14 миллиардов строк без повторения некоторых ключей. Максимум будет 52 * 52 * 52 * 52 = 7,311,616. Значит, здесь что-то не так…
5. это потому, что есть дополнительный ключ, состоящий еще из 3 карт. В настоящее время они находятся в отдельных файлах, поэтому я не упоминал об этом. Не могли бы вы привести мне пример массива коротких замыканий 5-dim и как получить доступ к данным. Я не совсем понимаю, что вы имеете в виду, но это звучит многообещающе
Ответ №1:
Я не уверен, какова ваша ценность. Как мало вы могли бы закодировать свои ценности? Я предполагаю, что вы можете упаковать их в 4 байта.
Таким образом, ваш ключ-это текстовая строка, описывающая 4 игральные карты. Таким образом, ваше возможное пространство для ключей-самое большее 52^4 ~= 7.3e6
. Из всех возможных ключей какая доля будет иметь значение? Это близко ко всем из них?
Вместо того, чтобы использовать текстовую строку для представления вашего ключа, я бы вместо этого присвоил каждой карте номер (0-51). Затем создайте Int32
ключ =k1 k2*52 k3*(52^2) k4*(52^3)
.
Если вы сохраняете значение для большинства ключей, то вам не нужен словарь. Вы можете просто использовать массив длины 52^4
. Таким образом, вам никогда не нужно выделять память для самих ключей. Требуется только 4bytes * 52^4 ~= 28MB
оперативная память.
Затем, чтобы сохранить этот массив на диске, я бы сохранил его в zip-архиве. Что должно хорошо сжиматься, если у вас много похожих значений.
Возможно, вы захотите разделить эти данные на несколько разделов, чтобы вам не пришлось распаковывать всю структуру в память. Но это будет зависеть от того, как вы собираетесь использовать эти данные во время выполнения.
Комментарии:
1. Привет, Джереми. Вы упомянули о хранении массива на диске в zip-архиве. Будет ли это означать запись массива в виде текстовых строк и сжатие текста? Или есть какой-то способ записывать и сжимать int, занимая меньше памяти, чем строки?
2. Файлы-это просто массивы байтов, вам понадобится способ упаковать / распаковать ваши значения в массив, а затем записать его. например docs.microsoft.com/en-us/dotnet/api/… ?
Ответ №2:
В соответствии с ограничениями, упомянутыми в ваших комментариях, вы можете поместить показанные примеры данных в 5-мерный массив. Вы просили образец, вот он. Я возьму первую строку из ваших выборочных данных:
4c5c,6c4h,486,30
Во-первых, вам нужно будет присвоить карточкам числовые значения. Вам решать, как вы их пронумеруете от 0 до 51. Для простоты я буду использовать
4c = 0
5c = 1
6c = 2
4h = 3
Массив будет выглядеть примерно так:
var data = new short [52, 52, 52, 52, 2];
Первые четыре измерения представляют ключи (номера карточек от 0 до 51), 5-е-индекс значений (0 или 1).
Затем вы можете получить доступ к своему массиву следующим образом (здесь я задам значения из первой строки в ваших образцах данных).:
data[0, 1, 2, 3, 0] = 486;
data[0, 1, 2, 3, 1] = 30;
Если есть недопустимые или нежелательные комбинации карт, просто не помещайте их в массив (все элементы по умолчанию инициализированы 0). Этот массив будет иметь фиксированный размер 29 246 464 байта. Доступ к элементам массива по номерам карт-самый быстрый из возможных способов. Но, как я уже писал в своих комментариях, это только для вашей представленной структуры данных. Неясно, как связаны другие три карты, этот массив может создавать только ваш представленный образец данных. Все еще надеюсь, что это поможет.