Есть ли более быстрый способ чтения больших данных, чем fread ()? - PullRequest
4 голосов
/ 31 мая 2019

Привет, во-первых, я уже ищу в стеке и в гугле и нашёл такие посты: Быстрое чтение очень больших таблиц в виде фреймов данных . Хотя они полезны и хорошо ответили, я ищу дополнительную информацию.

Я ищу лучший способ чтения / импорта "больших" данных, которые могут достигать 50-60 ГБ. В настоящее время я использую функцию fread() из data.table, и эта функция является самой быстрой из известных мне на данный момент. ПК / сервер, на котором я работаю, получил хороший процессор (рабочую станцию) и 32 ГБ ОЗУ, но все же данные, превышающие 10 ГБ, а иногда и миллиарды наблюдений, требуют много времени для чтения.

У нас уже есть базы данных sql, но по некоторым причинам нам приходится работать с большими данными в R. Есть ли способ ускорить R или даже лучший вариант, чем fread(), когда дело доходит до такого огромного файла?

Спасибо.

Редактировать: fread ("data.txt", verbose = TRUE)

omp_get_max_threads() = 2
omp_get_thread_limit() = 2147483647
DTthreads = 0
RestoreAfterFork = true
Input contains no \n. Taking this to be a filename to open
[01] Check arguments
  Using 2 threads (omp_get_max_threads()=2, nth=2)
  NAstrings = [<<NA>>]
  None of the NAstrings look like numbers.
  show progress = 1
  0/1 column will be read as integer
[02] Opening the file
  Opening file C://somefolder/data.txt
  File opened, size = 1.083GB (1163081280 bytes).
  Memory mapped ok
[03] Detect and skip BOM
[04] Arrange mmap to be \0 terminated
  \n has been found in the input and different lines can end with different line endings (e.g. mixed \n and \r\n in one file). This is common and ideal.
[05] Skipping initial rows if needed
  Positioned on line 1 starting: <<ID,Dat,No,MX,NOM_TX>>
[06] Detect separator, quoting rule, and ncolumns
  Detecting sep automatically ...
  sep=','  with 100 lines of 5 fields using quote rule 0
  Detected 5 columns on line 1. This line is either column names or first data row. Line starts as: <<ID,Dat,No,MX,NOM_TX>>
  Quote rule picked = 0
  fill=false and the most number of columns found is 5
[07] Detect column types, good nrow estimate and whether first row is column names
  Number of sampling jump points = 100 because (1163081278 bytes from row 1 to eof) / (2 * 5778 jump0size) == 100647
  Type codes (jump 000)    : 5A5AA  Quote rule 0
  Type codes (jump 100)    : 5A5AA  Quote rule 0
  'header' determined to be true due to column 1 containing a string on row 1 and a lower type (int32) in the rest of the 10054 sample rows
  =====
  Sampled 10054 rows (handled \n inside quoted fields) at 101 jump points
  Bytes from first data row on line 2 to the end of last row: 1163081249
  Line length: mean=56.72 sd=20.65 min=25 max=128
  Estimated number of rows: 1163081249 / 56.72 = 20506811
  Initial alloc = 41013622 rows (20506811 + 100%) using bytes/max(mean-2*sd,min) clamped between [1.1*estn, 2.0*estn]
  =====
[08] Assign column names
[09] Apply user overrides on column types
  After 0 type and 0 drop user overrides : 5A5AA
[10] Allocate memory for the datatable
  Allocating 5 column slots (5 - 0 dropped) with 41013622 rows
[11] Read the data
  jumps=[0..1110), chunk_size=1047820, total_size=1163081249
|--------------------------------------------------|
|==================================================|
Read 20935277 rows x 5 columns from 1.083GB (1163081280 bytes) file in 00:31.484 wall clock time
[12] Finalizing the datatable
  Type counts:
         2 : int32     '5'
         3 : string    'A'
=============================
   0.007s (  0%) Memory map 1.083GB file
   0.739s (  2%) sep=',' ncol=5 and header detection
   0.001s (  0%) Column type detection using 10054 sample rows
   1.809s (  6%) Allocation of 41013622 rows x 5 cols (1.222GB) of which 20935277 ( 51%) rows used
  28.928s ( 92%) Reading 1110 chunks (0 swept) of 0.999MB (each chunk 18860 rows) using 2 threads
   +   26.253s ( 83%) Parse to row-major thread buffers (grown 0 times)
   +    2.639s (  8%) Transpose
   +    0.035s (  0%) Waiting
   0.000s (  0%) Rereading 0 columns due to out-of-sample type exceptions
  31.484s        Total

Ответы [ 2 ]

3 голосов
/ 01 июня 2019

Предполагая, что вы хотите, чтобы ваш файл полностью считывался в R, использование базы данных или выбор поднабора столбцов / строк не очень поможет.

Что может быть полезно в таком случае:
- обеспечитьчто вы используете последнюю версию data.table
- убедитесь, что установлено оптимальное количество потоков
, используйте setDTthreads(0L) для использования всех доступных потоков, по умолчанию data.table использует 50% доступных потоков.
- проверьте вывод fread(..., verbose=TRUE) и, возможно, добавьте его к вашему вопросу здесь
- поместите ваш файл на быстрый диск или RAM-диск и прочитайте оттуда

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

2 голосов
/ 31 мая 2019

Вы можете использовать select = columns только для загрузки соответствующих столбцов без насыщения вашей памяти. Например:

dt <- fread("./file.csv", select = c("column1", "column2", "column3"))

Я использовал read.delim(), чтобы прочитать файл, который fread() не смог загрузить полностью. Таким образом, вы можете конвертировать ваши данные в .txt и использовать read.delim().

Однако, почему бы вам не открыть соединение с сервером SQL, с которого вы извлекаете данные? Вы можете открыть соединения с серверами SQL с помощью library(odbc) и написать свой запрос, как обычно. Таким образом вы можете оптимизировать использование памяти.

Ознакомьтесь с этим кратким введением до odbc.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...