Тема: Швидке сховище даних

Потрібно зберегти структуру виду

1: 84,
2: 120,
456903: 587411

до якої потім можна буде звертатися по ключу. Для цього в .NET підходить словник (ключі типу Int64 і значення теж Int64), але записів може бути декілька мільйонів і в оперативну пам'ять воно не поміщається. Запис в таблицю RDBMS SQLite триває занадто довго. Можна якось так це все записати щоб потім не потрібно було весь файл завантажувати до ОП або шукати в файлі рядок з потрібним ключем? Щоб можна було просто вказати ключ і отримати потрібне значення?

2 Востаннє редагувалося koala (23.05.2018 12:31:47)

Re: Швидке сховище даних

Кілька мільйонів чисел не поміщаються в оперативку? У вас що, комп середини 2000-х? 100 мільйонів 32-бітних чисел - це 400MB, цілком лізе одним масивом.
В цілому ж робите такий файл і тупо за потрібним зміщенням (множити на розмір int-а) записуєте потрібне число, потім простим lseek/gseek знаходите.
Трохи дивно, що SQLite таке не тягне. Так, він злегка загальмований, але ж тут не якесь диво треба зробити. Може, покажете запити?

3 Востаннє редагувалося javascriptIsLife (23.05.2018 12:59:48)

Re: Швидке сховище даних

3 гібібайти опертивної пам'ті. Дані в оперативці вже займають мебібайт 600. Якщо почати заповнювати об'єкт типу Dictionary, то через деякий час програма вилітає з повідомлення про те що закінчилась оперативна пам'ять.

4

Re: Швидке сховище даних

Вам треба по числу отримати число. Тобто звичайний масив, якщо є розумні обмеження на число. Можна ще в хеш-таблицю погратися.
Ну, або дійсно робіть собі файл на 4*2^32 байт і по зміщеннях все кладіть.

5 Востаннє редагувалося javascriptIsLife (23.05.2018 13:22:43)

Re: Швидке сховище даних

Власне задача полягає в тому що потрібно відсортувати велику кількість даних і записати в файл. Є CSV файл з якого по певним критеріям відбираються дані і записуються в інший CSV файл. Даних багато в опертивку не вміщаються, файл читається порядково. Як їх відсортувати в алфавітному порядку по вказаному полю, наприклад найменуванню товара, і записати відсортованими в вихідний файл? Як я роблю зараз: при першому проході в словник як ключі записуються ідентифікатори рядків які складаються зі значень двох полів. В якості значень словника виступають списки об'єктів з даними про номер рядка і ціну товару (структура виду avbcbdhdjd: {obj1, obj2, obj3…}, zcsadsadsad: {…}). Зі словників відбирається по одному значенню (з найменшою ціною) і записуються в новий словник в якому ключі ті ж самі що й в першому словнику, але значення вже не списки об'єктів а один об'єкт (avbcbdhdjd: obj100), перший словник очищається від даних. Другий словник сортується по ключам в алфавітному порядку. Виконується код який рахує зміщення в байтах всіх рядків від початку файлу. Робиться це так: файл читається порядково, рахується довжина в байтах кожного зчитаного рядку (кодування файлу Windows-1251) + 1 на символ \n і додається до попереднього значення (наприклад довжина першого рядку 120, 120 записується в змінну ініціалізовану нулем (0 + 120); довжина другого рядка 90. 90 додається до попереднього значення 120 (120 + 90 = 210). Виходить що зміщення другого рядка становить 210.). Я розраховував на те що ці дані будуть записуватися в словник ключами якого будуть номера рядків а значеннями ключів будуть зміщення (адреси) цих рядків (рядок №2, зміщення 210) і я буду обходити відсортований словник з найменшими цінами в якому вже є інформація про номера рядків і по ключу (номеру рядка) буду дізнаватися потрібне зміщення рядка, встановлювати файлів потік на потрібне зміщення, зчитувати з цього зміщення рядок і записувати в файл (і оскільки словник вже відсортований в потрібно порядку, то дані в вихідний файл записуються теж в потрібному порядку), але в якийсь момент закінчується ОП. Якщо хтось знає кращий алгоритм, то поділіться.

6 Востаннє редагувалося javascriptIsLife (23.05.2018 13:18:11)

Re: Швидке сховище даних

Всі запити полягають в тому що я в циклі записую в таблицю дані про помер рядка і його зміщення.

Public Function KnowLineBytesLength(ByRef line As System.String) As System.Int64
  Return CType(System.Text.Encoding.GetEncoding(1251).GetBytes(line).Length, System.Int64) + 1
End Function

Dim overallLength As System.Int64 = 0

While Not Reader.EndOfData
  line = Reader.ReadLine()
  ' Порахувати довжину рядка
  lineLength = KnowLineBytesLength(line)

  overallLength = overallLength + lineLength
  insertCommand = New SQLiteCommand("INSERT INTO lineoffsets (line, offset) VALUES(" & Reader.LineNumber & ", " & overallLength & ")", sqliteConnection)
  insertCommand.ExecuteNonQuery()
End While

7 Востаннє редагувалося koala (23.05.2018 13:10:21)

Re: Швидке сховище даних

А який розмір .csv?
І яка кінцева мета - просто отримати відсортований файл?
Бо загалом саме для цього і придумали БД - щоб не писати типовий код обробки даних кожного разу.
Можливо, встановити щось краще за SQLite - той же MySQL?

8

Re: Швидке сховище даних

Розмір 1,1 GiB. На основі файлу отримати інший відсортований по певний критеріям файл в CSV.

9

Re: Швидке сховище даних

З MySQL дані в БД будуть записувати швидше?

10

Re: Швидке сховище даних

В SQLite було б краще пхати по 1000 рядків за раз... але то таке. Вам воно обов'язково на Васіку чи можна іншими мовами?

11 Востаннє редагувалося koala (23.05.2018 13:24:07)

Re: Швидке сховище даних

Поки що так:
- збираєте виключно зміщення рядків у масив (Array);
- пишете об'єкт-компаратор, що імплементує інтерфейс IComparer, а саме перекручує на потрібні зміщення в файлі і порівнює;
- викликаєте Array.Sort із цим компаратором;
- пробігаєте по готовому масиву, читаєте по зміщенню рядки і переписуєте у новий файл.

12

Re: Швидке сховище даних

В мене вся програма на Visual basic.NET. Вже майже 1000 рядків коду. Не хотілося б переписувати. Ви щось краще придумали?

13

Re: Швидке сховище даних

До речі, як так сталося, що з таким ніком ви навіть не на JScript.NET пишете?

14

Re: Швидке сховище даних

Тому що мені не подобається JavaScript. На щось таке з під…ом фантазії не вистачило.

15

Re: Швидке сховище даних

Сумна історія у вашого ніка.
То як, зробили?

16

Re: Швидке сховище даних

Ні.

17 Востаннє редагувалося javascriptIsLife (23.05.2018 15:55:36)

Re: Швидке сховище даних

Виникла ідея створювати в каталозі декілька мільйонів каталогів з номерами рядків в якості імен і в кожному каталозі файл зі значенням зміщення. Номера рядків вже є. Потрібно буде перейти у відповідний каталог, прочитати вміст файлу і таким чином отримати зміщення.

18

Re: Швидке сховище даних

За 5 годин і 22 хвилини в БД було додано 123612 записів.

19

Re: Швидке сховище даних

Ставте якусь притомну СУБД.

Подякували: ReAl1

20 Востаннє редагувалося ReAl (23.05.2018 16:15:58)

Re: Швидке сховище даних

javascriptIsLife написав:

Виникла ідея створювати в каталозі декілька мільйонів каталогів

Щось мені така ідея не подобається :-)

Якщо вже дуже неохота слухатися koala, тоді вже (максимум) 4096 каталогів (по перших 3 шістнадцяткових цифрах int64), у кожному (знову максимум) 4096 підкаталогів (по наступних 3 цифрах), у кожному по максимум 4К файлів на максимум 64К записів (упорядковані, весь файл у пам'ять і двійковий пошук, файл може бути серіалізацією вашого масиву).

Хоча це починає нагадувати пошуки «на кухні» власного генератора псевдовипадкових чисел.

p.s. та ні, все одно фігня, залежна від розподілу ключів. Тому дійсно бажано геш-таблицю. І буде винайдено свій велосипед з одним трикутним колесом попереду і двома еліптичними зі зсувом на 90° позаду.