【问题标题】:SELECT data quickly without other rows interfering with %(mod) operator快速选择数据,其他行不会干扰 %(mod) 运算符
【发布时间】:2016-11-15 05:28:10
【问题描述】:

我有一个将历史结果记录到文件的数据库。

将结果记录到由

创建的表中
CREATE TABLE Data (TimeID INTEGER NOT NULL REFERENCES StartTimes, 
                   TimeOffset REAL,
                   SensorID INTEGER NOT NULL REFERENCES Sensors,
                   Value REAL);

我有一个超过 (TimeID, TimeOffset) 的索引,可以根据需要创建更多 - 我的 INSERT 性能暂时还不错,希望应该保持这样。

我读出数据以将数据放在图表上使用

SELECT SensorID, TimeOffset, Value from Data 
WHERE ((TimeID = %d AND TimeOffset BETWEEN %f AND %f) AND 
(%s));

其中 %s 由字符串替换,效果为“(SensorID=1 and ROWID%5=0) or (SensorID=2 and ROWID%5000=0)”,%d 是准备好的语句中的常量值, %f 必然与图的界限相对应。

我的问题是,如果我有两个传感器记录相同的速率,每个传感器记录一个点,并且如果我使用取模的值变成例如2,然后我从一个传感器获取所有数据,而从另一个传感器获取任何数据(我认为?)。

我尝试过使用

SELECT COUNT(lesser.TimeOffset) as NewID, D.TimeOffset from Data as D
LEFT OUTER JOIN Data as lesser on D.rowid > lesser.rowid and D.TimeID=%d and D.SensorID=1
GROUP BY D.TimeOffset;

但在命令行上(使用 TimeID 的示例值)命令行处理了很长时间(可能我完全写错了语句)。

如何使用这些约束(TimeID=?、TimeOffset BETWEEN ? AND ?)选择数据子集,并通过 SensorID 快速抓取不受写入其他测量值影响的集合?

理想情况下,我希望能够使用 MIN(x) 和 MAX(x) 来查找给定 TimeOffset 范围内的最高和最低值,但我似乎无法快速做到这一点(即我可以锻炼 - 不过我是 SQL(ite) 的新手)。因此,我只选择了 % 运算符。

编辑 - 示例表内容:

SELECT * from Data LIMIT 10;

TimeID|TimeOffset|SensorID|Value
1|0.0|1|0.464069664478302
1|0.0|2|0.0
1|0.00100000004749745|2|0.00251327152363956
1|0.0020000000949949|2|0.00502652721479535
1|0.00300000002607703|2|0.00753975100815296
1|0.00400000018998981|2|0.010052926838398
1|0.00499999988824129|2|0.0125660402700305
1|0.00600000005215406|2|0.0150790736079216
1|0.00700000021606684|2|0.0175920110195875
1|0.00800000037997961|2|0.0201048385351896

使用我的合成数据(用于测试实施),我有一个介于 0 和 1 之间的随机数作为 1Hz 的传感器 #1,以及一个正弦波作为 1kHz 的 #2。 (这些不是一次写的,但我仍然觉得我可以使用 rowid%x 来抽取自己的脚)

TimeOffset 测量自数据采集开始以来的时间,而 TimeID 引用 StartTimes 表(YmDHMS 等)中的 StartTime。

理由

由于屏幕上的像素通常远少于可放置在相关时间跨度内的点数,因此只选择一些点以减少我尝试从数据库中读取的数据量是明智的。

使用 % 运算符可以得到均匀分布的点,但在某些情况下很容易丢失数据的形状。

使用最小/最大抽取可以防止这种情况,但要使用它,您需要在每个时间跨度中找到最小值和最大值,例如一个像素的宽度。如果我不在查询中执行此操作,那么我必须从数据库中读取图表边界之间的所有数据,其中我可能只会绘制一小部分(低于 1%)。

【问题讨论】:

  • 我也可以考虑为每个传感器使用单独的表,但我不确定这会是一个更快的想法。不过,它会从问题中删除其他传感器的结果,这可能是值得的。
  • 如果您添加以下示例可能会有所帮助:您的表格内容、当前检索到的结果及其查询以及所需的结果。
  • 看来WITH 子句可以显着改善我的查询。我可以使用它们只取整个Data 表的一小部分,然后在该子集上执行JOIN,而没有对ON 子句的额外约束(这似乎是问题)。子查询不允许使用索引吗?还是我发布的查询永远不会超过JOIN

标签: sql select sqlite subquery


【解决方案1】:

您可以尝试使用子查询计算数据采集系列中条目的索引,但这会很慢。

过滤掉不需要的行的最有效方法可能是在您的程序中执行此操作,即以正确的顺序查询所有行,然后遍历除每个 n之外的所有行>-th。 (这需要排序,但ORDER BY TimeID, TimeOffset 不会花费任何成本,因为结果由于索引已经排序。)

您可以使用covering index 进一步改进您的查询,但对于此表,clustered index(前三列的 PK)会更好。 另外,使列的顺序为TimeID, SensorID, TimeOffset,因为only the right-most used column in an index can optimize inequalities

【讨论】:

  • 我知道当我使用SELECT 语句时,我应该使用TimeID, SensorID, TimeOffset 顺序中的约束,但我只是想检查一下——你的意思是这里,还是顺序CREATE TABLE 存储的列也对性能有一些影响?我会看看使用WITHOUT ROWID 表,看看我是怎么做的 - 只要我在应用程序中处理而不是你说的数据库(因为在那里我可以使用数组索引)
  • SELECT语句中的顺序无关紧要,只有索引中的顺序。 (在聚集索引中,这就是表顺序。)
  • 糟糕。最好检查一下我当时没有搞砸。将重读聚集索引。
猜你喜欢
  • 2012-06-05
  • 2021-12-27
  • 2012-07-14
  • 1970-01-01
  • 1970-01-01
  • 2016-01-22
  • 2012-04-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多