SQLite查询性能:更新与加入
我已经为此奋斗了几个星期了——正如你所看到的和所看到的。虽然我在那里得到的答案是正确的,但由于性能问题,它们不适合我。下面是更多 我正在使用SQLite。我有一个表,其中的行表示某个时间点中的个人。我正在尝试使用另一列status的滞后值创建列statusLag,如下所示:SQLite查询性能:更新与加入,sql,sqlite,Sql,Sqlite,我已经为此奋斗了几个星期了——正如你所看到的和所看到的。虽然我在那里得到的答案是正确的,但由于性能问题,它们不适合我。下面是更多 我正在使用SQLite。我有一个表,其中的行表示某个时间点中的个人。我正在尝试使用另一列status的滞后值创建列statusLag,如下所示: workerID timeVar status statusLag --------------------------------------------- 1 1
workerID timeVar status statusLag
---------------------------------------------
1 1 0 NULL
1 2 1 0
1 3 1 1
1 4 1 1
----------------------------------------------
2 3 1 NULL
2 4 0 1
2 5 1 0
2 6 0 1
我试过的
方法1:更新
我不清楚这是否会起作用。此外,这是我第一次加入,我的印象是,仅此查询不会在myTable上插入或更新任何内容。我需要补充这个查询来完成我在文章开头解释的内容吗
任何想法,任何帮助,非常感谢。我已经为此苦苦挣扎了两周,我需要完成这项工作。如果要更改表中的值,则需要使用update、insert或delete 如果这是您的查询:
UPDATE myTable
SET statusLag = (SELECT t2.status
FROM myTable t2
WHERE t2.workerID = myTable.workerID AND
t2.timeVar < myTable.timeVar
ORDER BY t2.timeVar desc
LIMIT 1
);
然后您可能有机会使用myTableworkerId、timeVar和status上的索引。但是,老实说,对于32亿行和16GB的RAM,这可能仍然没有帮助
几乎任何其他数据库都有可能帮助MySQL中变量滞后的结构。是否有可能使用另一个数据库?您可以尝试的一种策略是将其分解为多个较小的更新 也就是说,您不会试图一次更新32亿行。找到一种方法,把它分成30组,每组1亿行,一次一组 这有几个缺点: 在一段时间内,您将更新一些行,而一些行未更新。 你必须想办法把它们分成可用的块。 但最大的优势是它最终可能会起作用 比如:
UPDATE myTable
SET statusLag = (SELECT t2.status
FROM myTable t2
WHERE t2.workerID = myTable.workerID AND
t2.timeVar < myTable.timeVar
ORDER BY t2.timeVar desc
LIMIT 1
)
WHERE companyID = 1;
并为数据库中的每个companyID运行它
或
等等
重要的是让数据库进行更新,并在移动到下一组要更新的记录之前完成事务。如果您试图将其全部打包到一个事务中,那么您将遇到同样的问题,即必须在动态更新中管理32亿行的更新
您可能希望自动更新,例如编写一些java或其他东西来循环公司ID,或者您可以简单地使用体面的文本编辑器创建30或40条SQL语句,然后手动运行它们
如果您需要维护此数据,那么我建议您在创建行时包含滞后数据-一次一个比这样的大批量容易得多。更新操作很慢,因为数据库引擎必须获取行,运行子查询以获取新值,然后将行存储到位。有时它不适合它所在的位置,必须放在仓库的其他地方 为了获得更好的性能,我希望这样做: 使用statusLag列创建一个表myLagTable 运行一个INSERT,请参见下文 将myTable重命名为myOldTable 将myLagTable重命名为myTable 这样,myTable在重命名操作期间不可用 要填充myLagTable,可以使用连接: 请注意,我删除了ORDER BY,因为在INSERT中不需要它,它将使用Resources CPU、内存和磁盘对行进行排序
一旦您对结果感到满意,您可以删除myOldTable当我有时间投资建立一个数据库时,将有机会使用另一个数据库。加入是一个糟糕的解决方案吗?@djas。join可以,但不会更改数据。
UPDATE myTable
SET statusLag = (SELECT t2.status
FROM myTable t2
WHERE t2.workerID = myTable.workerID AND
t2.timeVar < myTable.timeVar
ORDER BY t2.timeVar desc
LIMIT 1
);
UPDATE myTable
SET statusLag = (SELECT t2.status
FROM myTable t2
WHERE t2.workerID = myTable.workerID AND
t2.timeVar < myTable.timeVar
ORDER BY t2.timeVar desc
LIMIT 1
)
WHERE companyID = 1;
WHERE companyID => 0 AND companyID < 1000;
INSERT INTO myLagTable(workerID, timeVar, status, statusLag)
SELECT t1.*, t2.status as statusLag
FROM myTable AS t1
LEFT JOIN myTable AS t2
ON t1.workerID=t2.workerID AND t1.timeVar=t2.timeVar+1;