Сохранить результаты запроса RSQLite в csv, не читая их в R

Я работаю с большой базой данных SQLite и использую RSQLite и Rstudio для одновременного выполнения множества разных запросов. Часто результаты запросов довольно велики, и я не хочу тратить ресурсы, читая их в R, а затем сохраняя в CSV. Я бы предпочел, чтобы сама база данных управляла этим. Однако это не работает, и я не уверен, что еще попробовать.

library(RSQLite)
db <- dbConnect(RSQLite::SQLite(), "test.sqlite")

dbWriteTable(db, "iris", iris)

dbListTables(db)


sql <- ".headers on
.mode csv
.output C:/Users/jmc6538/Documents/testing/setosa.csv
SELECT * FROM iris WHERE Species = 'setosa';"

result <- dbSendQuery(db, sql)

Что выдает эту ошибку

> result <- dbSendQuery(db, sql)
Error: near ".": syntax error

Я пробовал вставлять различные комбинации escape-символов, и это не решает проблему.


person jamesguy0121    schedule 02.11.2020    source источник
comment
Вы пробовали dbExecute вместо dbSendQuery? Кроме того, вы можете удалить result <- и оставить только dbExecute(db, sql)   -  person maloneypatr    schedule 02.11.2020
comment
использование dbExecute тоже не сработало. Получил такое же сообщение об ошибке.   -  person jamesguy0121    schedule 02.11.2020


Ответы (2)


Синтаксис здесь неприемлем, поскольку эти инструкции основаны на инструменте SQLite. Это не простые операторы sql, а скорее командные строки для этого инструмента:

  1. Установите утилиту командной строки sqlite из здесь

  2. Следуйте этим инструкциям, возможно, изменив их для использования в R, например

    shell('sqlite3 -header -csv c:/sqlite/chinook.db "select * from tracks;" > tracks.csv')

Убедитесь, что SQLite3 находится на вашем пути, открыв cmd и набрав sqlite3. Если у вас есть ошибка sqlite is not recognized, вам нужно добавить папку установки, содержащую sqlite3.exe или аналогичную пути. Или вы можете установить рабочий каталог в R на

setwd("C:/[installation folder containing sqlite3.exe]")
shell('sqlite3 -header -csv c:/sqlite/chinook.db "select * from tracks;" > tracks.csv')
person CatalystRPA    schedule 02.11.2020
comment
Ооо, это хорошее предложение, я не подумал просто отправить запрос через командную строку. Утилита командной строки у меня уже была, и она почти работает. Команда перенаправления не работает. Это то, что у меня есть, system('sqlite3 -header -csv C:/Users/jmc6538/Documents/testing/test.sqlite "select * from iris where Species = \'setosa\';" > test.csv') и вывод в R печатает данные и говорит Error: near ">": syntax error Любые предложения. Пробовал указывать полный путь, ничего не дало. - person jamesguy0121; 02.11.2020
comment
Это потому, что я на Windows... конечно. Согласно system() документам, This means that it cannot be assumed that redirection or piping will work in system (redirection sometimes does, but we have seen cases where it stopped working after a Windows security patch), and system2 (or shell) must be used on Windows. system2() у меня не работало, а shell() работало. - person jamesguy0121; 02.11.2020

Так что я закончил тем, что сделал некоторую контрольную оценку для этого, сравнивая принятый ответ с чтением таблицы в R, а затем сохраняя в csv, так как моя цель состояла в том, чтобы сократить время вычислений. Думал, что это может быть полезно другим, и результаты довольно интересны. Я протестировал его на своем ноутбуке с Windows, а также на суперкомпьютере, к которому у меня есть доступ. Я сделал три таблицы разного размера для каждой среды.

Для моего ноутбука это были команды.

microbenchmark(
  sys = {shell('sqlite3 -header -csv C:/Users/jmc6538/Documents/testing/test.sqlite "select * from iris;" > C:/Users/jmc6538/Documents/testing/test.csv')},
  RSQLite = {
    db <- dbConnect(RSQLite::SQLite(), "test.sqlite")
    result <- dbSendQuery(db, sql)
    write.csv(dbFetch(result), "./test2.csv")
    dbClearResult(result)
    dbDisconnect(db)
  })

Таблицы разного размера представляли собой одну копию данных iris (150 строк), набора данных iris 4 502 раза (675 300 строк) и набора данных iris 450 200 раз (6 753 000 строк). Вот результаты в том же порядке.

Unit: milliseconds
    expr        min         lq      mean     median        uq       max neval cld
     sys 213.758862 216.612667 223.37484 217.858642 218.88561 342.42205   100   b
 RSQLite   6.981669   7.663255  10.08729   9.377483  10.90106  25.52816   100  a 

Unit: seconds
    expr       min        lq      mean    median        uq       max neval cld
     sys 10.633965 11.788077 12.844148 12.967207 13.757598 16.142357   100   b
 RSQLite  5.164632  6.791199  7.172043  7.351825  7.728878  8.486433   100  a 

Unit: seconds
    expr      min        lq      mean    median        uq       max neval cld
     sys 94.38379 101.36282 103.49785 102.98158 104.52018 114.95047   100   b
 RSQLite 48.48948  50.28782  53.18634  53.64562  55.80938  63.87987   100  a 

Таким образом, на моем ноутбуке использование RSQLite и write.csv всегда было значительно быстрее.

На суперкомпьютере число строк было 150, 900 000 и 9 000 000, а команды были

microbenchmark(
  sys = {system('sqlite3 -header -csv C:/Users/jmc6538/Documents/testing/test.sqlite "select * from iris;" > C:/Users/jmc6538/Documents/testing/test.csv')},
  RSQLite = {
    db <- dbConnect(RSQLite::SQLite(), "test.sqlite")
    result <- dbSendQuery(db, sql)
    write.csv(dbFetch(result), "./test2.csv")
    dbClearResult(result)
    dbDisconnect(db)
  })

И результаты.

Результаты тестирования суперкомпьютеров

На суперкомпьютере использование вызова system было быстрее для больших таблиц, но не для маленькой таблицы.

Редактировать: использование fwrite data.table для записи CSV ускорило метод RSQLite по сравнению с методом оболочки на суперкомпьютере. Я сделал только 10 повторений для столов 900 000 и 9 000 000, потому что не хотел ждать 100. Я думаю, что это лучший метод, если люди ищут скорость.

введите здесь описание изображения

person jamesguy0121    schedule 03.11.2020