sqlite read.csv.sql插入所有行,而不管其SQL子句中的WHERE子句

lnlaulya  于 2023-01-26  发布在  SQLite
关注(0)|答案(2)|浏览(145)

我使用下面的(伪)代码在R中导入巨大的CSV文件,当文件中只有相当小的一部分数据需要处理/导入,其他行应该被忽略时。我不把数据放在内存中,而是放在程序创建的SQLite数据库中。

library(sqldf)
suppressWarnings(read.csv.sql(
    file = input_file_path,
    sql = "
       create table mytable as 
       select
           . . .
       from
           file
       where
           . . .
      ",
    header = FALSE,
    sep = "|",
    eol = "\n",
    `field.types` = list( . . . )
    dbname = sqlite_db_path,
    drv = "SQLite"
))

如果我正确理解了read.csv.sql的文档,那么上面的CREATE TABLE语句中的WHERE子句可以保证只有满足WHERE子句条件的行才会被插入到创建的表mytable中。昨天晚上在一个测试中,我发现我的程序有些奇怪的行为。2我不得不导入一个大的CSV文件(超过100 000 000行),但只有一组10 000行是目标,所有其他行都必须忽略。上面的程序完成了这项工作,最后,上面的代码中所指示的创建的表mytable,只有10000行,这证明考虑了WHERE子句中的条件。但是,当我检查创建的SQLite数据库的大小时,它异常巨大(超过25 GB)。这不可能是10000行的大小。
因此,我很困惑。在导入过程中发生了什么?为什么SQLite数据库文件变得如此庞大,以至于只在mytable中插入了10000行,而其他的一切都被忽略了?这是正常的行为还是我没有正确使用read.csV.sql

wlwcrazw

wlwcrazw1#

编辑:这是对@G.Grothendieck在上面评论部分提出的建议的详细说明。

我没有使用read.csv.sql的经验,但是你可能想看看从shell命令导入输出。这样,你预处理csv,并且只导入结果。
例如,data.table::fread(cmd = 'findstr "^[^#]" test.csv', sep = "\n", header = FALSE)导入csv test.csv中所有不以#-字符开头的行。
因此,它导入(windows)命令的输出:findstr "^[^#]" test.csv到一个data.table,使用data.table::fread()的所有功能和它的参数。这也可以在 * nix环境下工作,但是你必须使用适当的shell命令(比如grep)。
注意,这种方法可能工作得很好(而且很快!),但是它不可能在多个操作系统上交换代码。

h9a6wy2h

h9a6wy2h2#

感谢@G. Grothendieck的澄清:
它首先使用dbWriteTable将文件写入数据库。然后对该文件进行操作。您可以考虑使用grep/findstr/xsv将感兴趣的行提取出来,并将其直接导入R. read.table(pipe(“grep...”),sep =“,”)或Windows findstr或xsv或其他csv实用程序,然后使用该实用程序代替grep。

相关问题