Sql:优化 BETWEEN 子句

2024-03-03

我写了一份声明,需要将近一个小时才能运行,因此我寻求帮助,以便我可以更快地完成此操作。那么我们开始吧:

我正在对两个表进行内部联接:

我有许多由间隔表示的时间间隔,并且我想仅从这些间隔内的测量中获取测量数据。

intervals:有两列,一列是间隔的开始时间,另一列是结束时间(行数 = 1295)

measures:有两列,一列包含度量,另一列包含进行度量的时间(行数 = 一百万)

我想要得到的结果是一个表格,第一列中包含度量,然后是度量完成的时间,所考虑间隔的开始/结束时间(对于时间在所考虑范围内的行,它将重复)

这是我的代码:

select measures.measure as measure, measures.time as time, intervals.entry_time as entry_time, intervals.exit_time as exit_time
    from
    intervals
    inner join  
    measures
    on  intervals.entry_time<=measures.time  and measures.time <=intervals.exit_time  
    order by time asc

Thanks


这是一个很常见的问题。

Plain B-Tree索引不适合这样的查询:

SELECT  measures.measure as measure,
        measures.time as time,
        intervals.entry_time as entry_time,
        intervals.exit_time as exit_time
FROM    intervals
JOIN    measures
ON      measures.time BETWEEN intervals.entry_time AND intervals.exit_time
ORDER BY
        time ASC

索引适合搜索给定范围内的值,如下所示:

,但不适用于搜索包含给定值的边界,如下所示:

我博客中的这篇文章更详细地解释了这个问题:

  • 邻接表与嵌套集:MySQL http://explainextended.com/2009/09/29/adjacency-list-vs-nested-sets-mysql/

(嵌套集合模型处理类似类型的谓词)。

您可以将索引设置为time,这样一来intervals将在连接中领先,范围时间将在嵌套循环内使用。这将需要排序time.

您可以创建空间索引intervals(可用于MySQL using MyISAM存储),其中包括start and end在一个几何列中。这边走,measures可以引导连接并且不需要排序。

然而,空间索引速度更慢,因此只有在度量很少但间隔很多的情况下这才会有效。

由于您的间隔很少但度量很多,只需确保您有一个索引measures.time:

CREATE INDEX ix_measures_time ON measures (time)

Update:

这是一个要测试的示例脚本:

BEGIN
        DBMS_RANDOM.seed(20091223);
END;
/

CREATE TABLE intervals (
        entry_time NOT NULL,
        exit_time NOT NULL
)
AS
SELECT  TO_DATE('23.12.2009', 'dd.mm.yyyy') - level,
        TO_DATE('23.12.2009', 'dd.mm.yyyy') - level + DBMS_RANDOM.value
FROM    dual
CONNECT BY
        level <= 1500
/

CREATE UNIQUE INDEX ux_intervals_entry ON intervals (entry_time)
/

CREATE TABLE measures (
        time NOT NULL,
        measure NOT NULL
)
AS
SELECT  TO_DATE('23.12.2009', 'dd.mm.yyyy') - level / 720,
        CAST(DBMS_RANDOM.value * 10000 AS NUMBER(18, 2))
FROM    dual
CONNECT BY
        level <= 1080000
/

ALTER TABLE measures ADD CONSTRAINT pk_measures_time PRIMARY KEY (time)
/

CREATE INDEX ix_measures_time_measure ON measures (time, measure)
/

这个查询:

SELECT  SUM(measure), AVG(time - TO_DATE('23.12.2009', 'dd.mm.yyyy'))
FROM    (
        SELECT  *
        FROM    (
                SELECT  /*+ ORDERED USE_NL(intervals measures) */
                        *
                FROM    intervals
                JOIN    measures
                ON      measures.time BETWEEN intervals.entry_time AND intervals.exit_time
                ORDER BY
                        time
                )
        WHERE   rownum <= 500000
        )

uses NESTED LOOPS并返回1.7秒。

这个查询:

SELECT  SUM(measure), AVG(time - TO_DATE('23.12.2009', 'dd.mm.yyyy'))
FROM    (
        SELECT  *
        FROM    (
                SELECT  /*+ ORDERED USE_MERGE(intervals measures) */
                        *
                FROM    intervals
                JOIN    measures
                ON      measures.time BETWEEN intervals.entry_time AND intervals.exit_time
                ORDER BY
                        time
                )
        WHERE   rownum <= 500000
        )

uses MERGE JOIN之后我不得不停止它5分钟。

更新2:

您很可能需要使用如下提示强制引擎在连接中使用正确的表顺序:

SELECT  /*+ LEADING (intervals) USE_NL(intervals, measures) */
        measures.measure as measure,
        measures.time as time,
        intervals.entry_time as entry_time,
        intervals.exit_time as exit_time
FROM    intervals
JOIN    measures
ON      measures.time BETWEEN intervals.entry_time AND intervals.exit_time
ORDER BY
        time ASC

The Oracle的优化器不够智能,无法看到间隔不相交。这就是为什么它很可能会使用measures作为领先表(如果间隔相交,这将是一个明智的决定)。

更新3:

WITH    splits AS
        (
        SELECT  /*+ MATERIALIZE */
                entry_range, exit_range,
                exit_range - entry_range + 1 AS range_span,
                entry_time, exit_time
        FROM    (
                SELECT  TRUNC((entry_time - TO_DATE(1, 'J')) * 2) AS entry_range,
                        TRUNC((exit_time - TO_DATE(1, 'J')) * 2) AS exit_range,
                        entry_time,
                        exit_time
                FROM    intervals
                )
        ),
        upper AS
        (
        SELECT  /*+ MATERIALIZE */
                MAX(range_span) AS max_range
        FROM    splits
        ),
        ranges AS
        (
        SELECT  /*+ MATERIALIZE */
                level AS chunk
        FROM    upper
        CONNECT BY
                level <= max_range
        ),
        tiles AS
        (
        SELECT  /*+ MATERIALIZE USE_MERGE (r s) */
                entry_range + chunk - 1 AS tile,
                entry_time,
                exit_time
        FROM    ranges r
        JOIN    splits s
        ON      chunk <= range_span
        )
SELECT  /*+ LEADING(t) USE_HASH(m t) */
        SUM(LENGTH(stuffing))
FROM    tiles t
JOIN    measures m
ON      TRUNC((m.time - TO_DATE(1, 'J')) * 2) = tile
        AND m.time BETWEEN t.entry_time AND t.exit_time

此查询将时间轴分割为多个范围并使用HASH JOIN将度量值和时间戳加入到范围值中,并在稍后进行精细过滤。

有关其工作原理的更详细说明,请参阅我的博客中的这篇文章:

  • Oracle:连接时间戳和时间间隔 http://explainextended.com/2009/12/28/oracle-joining-timestamps-and-time-intervals/
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Sql:优化 BETWEEN 子句 的相关文章

  • 带有 viewbags 的 MVC 数据集

    如何将数据集放入视图袋中并在视图中显示结果 我有一个来自模型的数据集 并将其写入视图包 我想使用 foreach 循环从视图中的视图包中获取数据行 我已经有一个变量进入视图 所以我无法正常传递数据集 每页我还会有许多其他数据集 所以我认为
  • 单向关系和双向关系的区别

    我想知道这两个词是什么意思 我遇到他们是在教义的文档 http www doctrine project org documentation manual 2 0 en association mapping 但我不明白他们的意思 这与常见
  • 获取 Postgres 数据库中每个表的行数

    获取数据库中所有表的行数的最有效方法是什么 我正在使用 Postgres 数据库 结果示例 table name row count some table 1 234 foobar 5 678 another table 32 如果您想要特
  • 使用子查询与 LEFT JOIN 一起选择 MAX 值

    我有一个获取搜索结果的查询 效果很好 查询成功示例 SELECT individuals individual id individuals unique id TIMESTAMPDIFF YEAR individuals day of b
  • MS Access:在列中搜索星号/星号

    我正在寻找一种方法来搜索包含字符串数据类型的列 问题是星号或星号是保留符号 以下查询无法正常工作 select from users where instr pattern 如何编写 Access 查询来搜索列中的星号 您可以使用方括号在
  • 如何使用 Java 创建多个模式连接?

    我必须使用两个数据库 DB2 Oracle 我在 DB2 数据库中有一个名为NAVID 我想使用 Java 为 Oracle 中的所有表创建相同的架构 public class automateExport static String va
  • 如何将 LEFT JOIN 限制为 SQL Server 中的第一个结果?

    我有一些 SQL 几乎可以做我想做的事情 我正在使用三个表 Users UserPhoneNumbers 和 UserPhoneNumberTypes 我正在尝试获取用户列表及其电话号码以供导出 数据库本身很旧并且存在一些完整性问题 我的问
  • 当我耗尽 bigint 生成的密钥时会发生什么?怎么处理呢?

    我自己无法想象一个好的答案 所以我想在这里问 在我心里 我总是想知道 如果AUTO INCREMENT PRIMARY ID我的专栏MySQL表用完了吗 举例来说 我有一个有两列的表 一个ID auto increment primary
  • 增量SQL查询

    我的应用程序有一组固定的 SQL 查询 这些查询以轮询模式运行 每 10 秒一次 由于数据库的大小 gt 100 GB 和设计 超级规范化 我遇到了性能问题 每当数据库上发生更改查询结果的 CRUD 事件时 是否可以对给定查询进行增量更改
  • JOOQ 查询 JOIN ON WITH 子句

    如何编写 JOOQ 查询来连接 with 子句中的字段 例如 我尝试过 create with a as select val 1 as x val a as y select from tableByName a join ANOTHER
  • 光标返回错误值 - sqlite - Android

    我正在开发一个短信应用程序 我正在尝试从每次对话中获取最后一条短信 这是我的 SQL 语句 SELECT MAX smsTIMESTAMP AS smsTIMESTAMP id smsID smsCONID smsMSG smsNUM sm
  • 如何更新 SQL Server 中 ntext 列中的 XML 字符串?

    有一个包含 2 列的 SQL 表 ID int 和值 ntext 值行中包含各种 xml 字符串 ID Value 1
  • 如何在jOOQ中使用别名

    有人可以指导我如何在 jOOQ 中使用别名吗 我尝试查看 jOOQ 文档 但不清楚 如果可能 请提供示例 Both org jooq Table http www jooq org javadoc latest org jooq Table
  • MySQL - 替换列中的字符

    作为一个自学成才的新手 我给自己制造了一个大问题 在将数据插入数据库之前 我将字符串中的撇号 转换为双引号 而不是 MySQL 实际需要的反斜杠和撇号 在我的表增长到超过 200 000 行之前 我认为最好立即纠正此问题 所以我做了一些研究
  • 查询从 Teradata 时间戳返回特定日期(6)

    我如何从 teradata timestamp 6 字段中搜索特定日期 例如 2013 10 22 sel from table A where date 2013 10 22 我尝试了上面的查询 该查询抛出错误 请帮忙 你可以这样尝试 s
  • 如何使用 WHERE x IN 子句编写PreparedStatement 的SQL?

    我有一个如下所示的查询 SELECT last name first name middle initial FROM names WHERE last name IN smith jones brown 我需要能够对 IN 子句中的列表进
  • 获取下一个ID而不插入行

    在 SQL SQL Server 中是否可以在插入行之前从表中的标识列检索下一个 ID 整数 而无需实际插入行 如果删除了最近的行 则这不一定是最高 ID 加 1 我问这个问题是因为我们偶尔需要用新行更新实时数据库 行的 ID 在我们的代码
  • 如何列出表中的所有列?

    对于各种流行的数据库系统 如何列出表中的所有列 对于 MySQL 请使用 DESCRIBE name of table 只要您使用 SQL Plus 或 Oracle 的 SQL Developer 这也适用于 Oracle
  • 如何对主索引重新编号

    我有一个简单的 MySQL 表 主索引 id 不是一一编号的 1 31 35 100 等 我希望它们的编号如 1 2 3 4 请告诉我该怎么做 我还想指出的是 我知道该操作可能产生的后果 但我只是想整理一下表格 我同意其他方法也可以 但我只
  • MySQL:查询中周数的周日期范围

    我有一个看起来像这样的数据库表 id clock info 1 1262556754 some info 2 1262556230 some other info 3 1262556988 and another 4 1262555678

随机推荐

  • 从子视图将 Javascript 文件附加到 InlineScript 集合的末尾

    我正在使用 Zend Framework 2 在我的布局文件中 我注入了一些像这样的 javascript 文件 this gt InlineScript gt appendFile this gt basePath js myfile j
  • ASP .NET MVC 保护控制器/操作

    如果我只想管理员访问名为 ManagerUser 的操作 我知道我可以这样做 Authorize Roles Constants ROLES ADMINISTRATOR public ActionResult ManageUser stri
  • Tomcat Maven 插件 - 子容器在启动期间失败

    我正在开发一个多模块 Maven 项目 我想在 Tomcat 7 中运行我的 Web 项目 但出现此错误 子容器在启动期间失败 我继续 右键单击网络项目 gt 运行方式 gt 运行配置 gt 目标 tomcat7 run 我有这个日志 av
  • 数据表自动切换页面

    我正在尝试自动在数据表页面之间切换 但似乎无法使其正常工作 我要么得到一个长时间运行的脚本 如果我尝试添加延迟 则会收到以下错误 table page draw delay 不是函数 下面是我正在使用的代码 document ready f
  • 反斜杠字符的 Bash 参数扩展规则

    我有一个变量 我想使用双反斜杠 替换每次出现的反斜杠 外壳参数扩展 https www gnu org software bash manual html node Shell Parameter Expansion html 最初 我使用
  • 从子目录中的不同文件导入类

    这是我正在使用的结构 directory script py subdir init py myclass01 py myclass02 py 我想要做的是在 script py 中导入定义的类myclass01 py and myclas
  • 展平 pandas 中的嵌套 json

    我收到了 JSON 格式的天气观测数据 我想将其展平 一份完整记录 第一个位置包含 25 个报告 Rep in Period SiteRep DV type Obs Location i 3002 lat 60 749 lon 0 854
  • 有什么方法可以更改 VSTO Outlook 添加中的自定义任务窗格颜色吗?

    有没有办法更改邮件撰写窗口中的自定义任务窗格背景颜色 UPDATE UserControl BackColor 给了我这个结果 但我希望整个自定义任务窗格是白色的 我设置用户控件的代码在这里 public partial class Use
  • 如何使用 C++ ShellExecute 命令在特定页面或指定目的地打开 PDF

    我正在尝试打开一个 pdf在特定的指定目的地使用ShellExecute 但我不知道参数应该如何格式化 我这里使用的参数是pagew 以前有人尝试过这个吗 我找到了几个答案 但它们对我的需要没有帮助 PS 只打开 pdf工作正常 int m
  • “您需要将 Theme.AppCompat 主题(或后代)与设计库一起使用”错误

    每次我都会收到 您需要将 Theme AppCompat 主题 或后代 与设计库一起使用 错误 即使我显然使用的是 AppCompat 主题 后代主题 依赖项 compile com android support appcompat v7
  • 在 C# 中使用私钥对数据进行签名

    我需要使用算法 SHA1RSA Rsa 密钥长度 2048 和 64 基本编码 用一个私钥对一些数据进行签名 我的代码是这样的 string sPayload HttpWebRequest httpWebRequest HttpWebReq
  • 如何从 R 矩阵中随机选择重复的行样本?

    如何从 R 矩阵中随机选择重复的行样本 所以请明确一点 我将从一个 100 行的矩阵开始 我可以选择其中 5 行并创建一个新矩阵 我希望可以选择在更换或不更换的情况下执行此操作 Use sample在行上replace TRUE or re
  • 释放从 C 函数返回的内存

    在 C 中 在释放函数返回的内存时 这是更好的做法 提供一个 析构函数 来封装对 free 的调用 要求用户自己 free 返回的指针 例如 要打开和关闭文件 我们执行以下操作 FILE f fopen blah w fclose f 这是
  • 是否可以阻止 requireJS 自动添加 .js 文件扩展名?

    我正在使用 requireJS 来加载脚本 它有文档中的这个细节 http requirejs org docs api html config 用于模块名称的路径不应包含 js 扩展名 因为路径映射可能是目录 在我的应用程序中 我将所有脚
  • 平铺未在折叠工具栏中居中

    我尝试设置collapsingToolbarLayout setCollapsedTitleGravity Gravity CENTER collapsingToolbarLayout setExpandedTitleGravity Gra
  • 使用php和mysql查询结果获取父级下的所有子节点、孙子节点等

    我一直在试图解决这个问题 但我一无所获 希望有人能来拯救我 我的问题是我正在使用邻接列表数据模型在 mysql 中生成层次结构数据 我可以将表 见下文 检索到一个多维数组中 其中每个项目都有关联数组 我想要做的是 一旦我得到这个数组 我想得
  • Firebase从中间键上下查询数据

    我有一个有日期的数据列表 我通常查询按日期排序的数据 但我遇到的情况是 我需要从中间键来回检索一些数据 我有按日期排序的数据 orderByChild date 像这样 key1 date 2016 07 25 key2 date 2016
  • Body/HTML 元素缩小到比视口小得多

    我正在使我的 WordPress 网站具有响应能力 我正在处理的页面上有两个图像 我想将它们设置为max width100 使它们响应 这是我在我制作的另一个网站上所做的 并且效果很好 然而 我注意到当我在 Chrome 开发工具中缩小页面
  • 仅更改底部导航视图的一个图标的大小(Android)

    我只想更改底部导航视图中使用的 5 个图标中的一个图标 第三个图标 的大小 我想要中心图标像这样大 这是我尝试过的 private fun setReportPainIconSize val bottomNavigationView fin
  • Sql:优化 BETWEEN 子句

    我写了一份声明 需要将近一个小时才能运行 因此我寻求帮助 以便我可以更快地完成此操作 那么我们开始吧 我正在对两个表进行内部联接 我有许多由间隔表示的时间间隔 并且我想仅从这些间隔内的测量中获取测量数据 intervals 有两列 一列是间