日期/时间点/间隔的(关系)数据库性能

Posted

技术标签:

【中文标题】日期/时间点/间隔的(关系)数据库性能【英文标题】:(relational) database performance for a date/time point/interval 【发布时间】:2012-12-21 07:47:40 【问题描述】:

所以我在 Access SQL 中做一个项目,它进展顺利。我学到了很多关于 Access 和 VBA 的知识,这个网站在这个过程中很有帮助。

现在我面临一个性能问题,由于我在这种 SQL 工作方面的经验很少,所以我来这里思考一下。

我有一个约 20 个表的关系数据库,其中包含大约 100 个部分,它们代表路线的一部分。 Access 数据库本质上是一张地图,我在上面绘制了几条可以动态着色的路线(通过线) - 颜色由特定问题确定并从数据库中计算出来。

这是一张更好地解释它的图片。您不能单击访问中的线条,因此按钮的颜色和宽度设置为与线条相同,并且可以单击以获取更多信息。

用户可以选择一个日期,它会根据提出的问题显示路线的进度。到目前为止,这些问题始终是二元的“是或否”(绿色或红色)。

我发现由于查询的复杂性,我几乎必须在启动时为每个查询准备一个临时数据库,否则无法顺利滚动日期。

所以无论如何这是我的具体问题:

路线的每个部分都可以在特定日期处于不同的阶段(想想施工)。从“阶段 0”到“完成”

将实施代表项目阶段的新行。所有部分大约有 8 个可能的阶段,它们可能发生在不同的时间,而且 - 事情是这样的 - 每个部分的顺序不同,并且并非所有阶段都发生在所有部分上。

我在数据库中拥有的只是每个阶段的开始日期,而不是结束日期。阶段的顺序几乎由开始日期的顺序决定。 至少每个阶段每个部分只能发生一次,所以就是这样。 正如你所看到的,对于这种以性能为中心的程序来说,这是一件糟糕的事情。

我确信它会涉及一个或多个临时数据库。 我的想法:

    将所有日期聚合到新表的一行中。由于设置了阶段数,因此每个阶段都有列 - 如果需要,何时开始以及何时结束。现在需要一个循环遍历每个并检查用户日期是否属于哪个阶段。所以: “SectionID - phase1needed phase1start phase1end .....” 优势:

    可以手动确认数据并以辅助形式很好地显示 它使数据库保持小 缺点: 实际的循环需要经过(在最坏的情况下)所有阶段才能找到正确的阶段。

    计算一个新的数据库,它只是“IdSection - Date - Phase”,并计算每个 Section 的阶段和间隔内的每一天。 优势:

    这将运行时计算保持为每个部分一个查询 访问应处理大量数据 缺点: 我无法手动检查我所做的是否对所有部分都正确 启动时需要很长时间,就像真的很长一样 该数据库中需要大量条目

现在我问你更喜欢哪种方法,或者即使有不同的方法? 我无法真正改变我拥有的数据点。

简而言之,我必须显示不同阶段的时间间隔,并且在数据库中我只有时间起点,没有完整的阶段顺序。

感谢您的想法,任何此类事情的经验都会有所帮助

【问题讨论】:

+1 有趣的问题。在这个应用程序中看到 MS Access 的使用是独一无二的。 是的,我知道,Access 中的表单和报告有很多限制,但它确实有效!它实际上是为了实习,这里并没有真正的 IT 人员,而 Access 是我们拥有的唯一可能产生这种东西的程序(没有 ms studio 或 sql server 或其他)。所以我必须使用我所拥有的。如果这意味着绘制 500 条线段和按钮,那就这样吧。有点需要这个;) 使用选项 1,“实际的循环需要经过(最坏的情况下)所有阶段才能找到正确的阶段”,我们说的可能有多少? 第二个选项似乎是经典的解决方案,但我看不到“启动时需要很长时间,就像真的很长一样”或“该数据库中需要很多条目”。为什么需要很长时间? “很多”是多少?哪个版本或 Access? @Matt:我们谈论的是 10 个阶段,但我突然想到一个阶段可以多次出现(在施工期间停止)。所以基本上我必须找到一种不同的方法来为每个部分设置某种时间表。我想事先计算一下,因为我的(更微不足道的)计算现在已经花费了太长时间来处理。我想我对第一种方法的问题是:专业人士如何在数据库中保存时间表?每次计算开始/结束和查询? 【参考方案1】:

如果我理解正确的话,你有一系列类似于表格的数据:

Section 1, Phase 7, Start Date = 11/07/2012
Section 1, Phase 2, Start Date = 12/14/2012
Section 1, Phase 3, Start Date = 12/28/2012
Section 2, Phase 1, Start Date = 11/04/2012
Section 2, Phase 9, Start Date = 12/30/2012
Section 3, Phase 4, Start Date = 11/19/2012
Section 3, Phase 5, Start Date = 12/06/2012
Section 3, Phase 3, Start Date = 12/11/2012

您想回答“2012 年 12 月 15 日每个部分处于什么阶段?”之类的问题,对吗?

这种情况下的答案应该类似于以下形式:

Section 1, Phase 2
Section 2, Phase 1
Section 3, Phase 3

为了做到这一点,我假设您有一个名为 SECTION_PHASES 的表,其中包含以下字段:

SECTION    Number
PHASE      Number
START_DATE Date/Time

您需要做的是找出在您当前输入日期之前发生的每个部分的最长开始日期,因为这是在下一个阶段更改之前最近活跃的阶段。完成此操作后,您可以将该信息重新加入主表,以确定该日期之后的阶段。

您需要进行一次查询 SECTION_MAX_DATES,然后在其 SQL 视图中包含以下代码:

SELECT [SECTION_PHASES].SECTION, Max([SECTION_PHASES].START_DATE) AS target_date
FROM SECTION_PHASES
WHERE [SECTION_PHASES].START_DATE<#12/15/2012#
GROUP BY [SECTION_PHASES].SECTION
ORDER BY [SECTION_PHASES].SECTION;

保存该查询后,您可以将其作为子查询加入到原始表中。现在,进行另一个查询 SECTION_PHASE_AT_DATE ,其中包括您的原始表和上一个查询,然后在其 SQL 视图中输入以下代码:

SELECT SECTION_PHASES.SECTION, SECTION_PHASES.PHASE, SECTION_PHASES.START_DATE
FROM SECTION_MAX_DATES INNER JOIN SECTION_PHASES ON (SECTION_MAX_DATES.target_date=SECTION_PHASES.START_DATE) AND (SECTION_MAX_DATES.SECTION=SECTION_PHASES.SECTION)
ORDER BY SECTION_PHASES.SECTION;

如果我正确理解您的问题,该查询将为您提供您所追求的结果。如果我正确理解给定阶段的新开始日期表示在新日期之前的任何当前阶段的结束,则无需计算结束日期。

您仍然需要解决一些边缘情况,例如如果某个部分在给定日期之前还没有注册阶段会发生什么。我还将让您弄清楚如何在两个查询中的第一个的 WHERE 子句中参数化日期,考虑到您已经取得的进展,这对您来说可能是微不足道的!但是,我认为这是您为解决问题的数据/计算部分而寻找的 SQL 结构。

【讨论】:

这里有一些澄清:我认为您的问题是您想为 10 个不同阶段绘制另一条具有 10 种不同颜色的彩色线和条,并且您需要知道每个部分处于哪个阶段给定日期。你和其他几个人一直在提到一个阶段的结束日期,但你不需要它来解决这个问题。我相信您想要结束日期,因为您试图在单个查询中使用两个谓词来确定正确的阶段。但是,如果您编写了正确的查询,则没有必要这样做。 谢谢,我基本上已经实现了这个。我很高兴地报告该项目成功完成并取得了巨大的成功

以上是关于日期/时间点/间隔的(关系)数据库性能的主要内容,如果未能解决你的问题,请参考以下文章

presto计算日期间隔天数或者小时间隔——date_diff函数使用

MySQL 按日期查询大间隔

SQL DB 性能和短时间重复查询

MySQL 性能优化:按日期时间字段排序

请问两个时间点之间的间隔怎么算?

性能关注的点以及计算方式关系图