我有一个约140万行和16列的sqlite数据库。
我必须对80,000个id进行操作:
对于每个ID,我一直使用R的dbSendQuery和dbFetch从R查询sqlite,而第2步和第3步是在R中完成的。有没有一种更快的方法?将整个sqlite表加载到data.table中会更快还是更慢?
答案 0 :(得分:1)
我在很大程度上取决于您如何解决该问题。
正常情况下,将整个查询加载到内存中,然后执行操作会比我在grahics上所见和见过的更快,我现在无法向您显示基准。从逻辑上讲,这很有希望,因为您必须在多个data.frames上重复多次操作。正如您在此处看到的,80k行非常快,比3x 26xxx行要快。
不过,您可以查看parallel
软件包,并在计算机上使用多个内核来加载数据子集并并行处理它们,每个子集都在多个内核上。
在这里您可以找到有关如何执行此操作的信息: http://jaehyeon-kim.github.io/2015/03/Parallel-Processing-on-Single-Machine-Part-I
答案 1 :(得分:1)
如果您要在R中进行所有操作,并在一个循环中从数据库中提取行80,000次,那么使用sqlite一次完成所有操作可能会得到更好的结果。
给出如下骨架表:
CREATE TABLE data(id INTEGER, timestamp TEXT);
INSERT INTO data VALUES (1, '2019-07-01'), (1, '2019-06-25'), (1, '2019-06-24'),
(2, '2019-04-15'), (2, '2019-04-14');
CREATE INDEX data_idx_id_time ON data(id, timestamp DESC);
查询,例如:
SELECT id
, julianday(first_ts)
- julianday((SELECT max(d2.timestamp)
FROM data AS d2
WHERE d.id = d2.id AND d2.timestamp < d.first_ts)) AS days_difference
FROM (SELECT id, max(timestamp) as first_ts FROM data GROUP BY id) AS d
ORDER BY id;
会给你
id days_difference
---------- ---------------
1 6.0
2 1.0
现代版本的sqlite(3.25或更高版本)的替代方法(编辑:在具有1600万行和80000个不同ID的测试数据库上,它的运行速度比上述数据库慢得多,因此您不想实际使用它):
WITH cte AS
(SELECT id, timestamp
, lead(timestamp, 1) OVER id_by_ts AS next_ts
, row_number() OVER id_by_ts AS rn
FROM data
WINDOW id_by_ts AS (PARTITION BY id ORDER BY timestamp DESC))
SELECT id, julianday(timestamp) - julianday(next_ts) AS days_difference
FROM cte
WHERE rn = 1
ORDER BY id;
(该索引对于这两个版本的性能都是必不可少的。可能要在填充它并创建索引之后的某个时刻在表上运行ANALYZE。)