如何创建非聚集索引以从 R 中的 SQLite DB 查询和收集数据以进行绘图?

问题描述

我有一个 .csv 文件,其中包含 1.05 亿行和 30 列,我想在 R 闪亮应用程序中查询这些文件以进行绘图。

它包含如下所示的字母数字数据:

        #Example data
        df<-as.data.frame(percent=as.numeric(rep(c("50","80"),each=5e2)),maskProportion=as.numeric(rep(c("50","80")),each=5e2),dose=runif(1e3),origin=as.factor(rep(c("ABC","DEF"),destination=as.factor(rep(c("XYZ","GHI"),each=5e2))
                          )

write.csv(df,"PassengerData.csv")

在终端中,我已将其摄取到 sqlite 数据库中,如下所示:

$ sqlite3 -csv PassengerData.sqlite3 '.import PassengerData.csv df'

来自:

Creating an SQLite DB in R from an CSV file: why is the DB file 0KB and contains no tables?

到目前为止一切顺利。

我遇到的问题是在 R 中查询的速度,所以我尝试在终端中索引数据库

sqlite3 中,我尝试按照此链接 https://data.library.virginia.edu/creating-a-sqlite-database-for-use-with-r/ 为百分比、掩码比例、来源和目的地创建索引:

$ sqlite3 create index "percent" on PassengerData("percent");
$ sqlite3 create index "origin" on PassengerData("origin");
$ sqlite3 create index "destination" on PassengerData("destination");
$ sqlite3 create index "maskProp" on PassengerData("maskProp");

我的磁盘空间用完了,因为每次创建索引时我的数据库似乎都会变大。例如。运行第一个命令后,大小为 20GB。我怎样才能避免这种情况?

解决方法

我认为问题在于运行 collect() 将数据从 SQL 传输到 R 对您的应用来说太慢了。不清楚在传递给 R 之前如何/是否在 SQL 中处理数据。

需要考虑的几件事:

  • 索引不会从 SQL 复制到 R。SQL 处理磁盘外的数据,因此知道在哪里查找数据的特定部分可以节省时间。 R 处理内存中的数据,因此不需要索引。
  • collect 将数据从远程表(在本例中为 SQLite)传输到 R 内存中。如果您的目标是将数据传输到 R,您可以将 csv 直接读入 R,而不是将其写入 SQL,然后再从 SQL 读入 R。
  • SQL 是进行数据处理/准备大型数据集的更好选择,而 R 是详细分析和可视化的更好选择。但是如果 R 和 SQL 都在同一台机器上运行,那么两者都受到 CPU 速度的限制。不必担心 SQL 和 R 在不同的硬件上运行。

您可以采取一些措施来提高性能:

(1) 只将你需要的数据从 SQL 中读入 R。 先在 SQL 中准备好数据。比如对比以下:

# collect last
local_r_df = remote_sql_df %>%
  group_by(origin) %>%
  summarise(number = n()) %>%
  collect()

# collect first
local_r_df = remote_sql_df %>%
  collect() %>%
  group_by(origin) %>%
  summarise(number = n())

这两者都会产生相同的输出。但是,在第一个示例中,汇总发生在 SQL 中,并且仅将最终结果复制到 R;而在第二个示例中,整个表被复制到 R 中,然后在那里进行汇总。最后收集可能比先收集具有更好的性能,因为它只在 SQL 和 R 之间传输少量数据。

(2) 为您的应用预处理数据。如果您的应用仅检查有限数量方向的数据,则可以对数据进行预处理/预汇总。

例如,假设用户最多可以选择两个维度并收到一个交叉表,那么您可以计算所有双向交叉表并保存它们。这可能比整个数据库小得多。然后在运行时,您的应用程序加载准备好的摘要并向用户显示他们请求的任何摘要。这可能会快得多。