AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 180409
Accepted
Chris Halcrow
Chris Halcrow
Asked: 2017-07-21 21:40:19 +0800 CST2017-07-21 21:40:19 +0800 CST 2017-07-21 21:40:19 +0800 CST

在 WHERE 中具有日期范围的 SQL Server 查询 - 执行计划使用聚集的 PK 实例而不是日期列索引

  • 772

我在 SQL Server 中有以下查询:

declare @timestamp_start date = getdate() - 1
declare @timestamp_end date = getdate()

SELECT  
    my_date = a.itemTimestamp
FROM
    my_table a with(nolock)
WHERE 
    (@timestamp_start is null OR a.itemTimestamp >= @timestamp_start)
    AND (@timestamp_end is null OR a.itemTimestamp < @timestamp_end)

它非常慢(< 2000 条记录需要 90 秒),因为执行计划使用 'my_table' 的 PK 列的聚集索引:

在此处输入图像描述

为什么会发生这种情况,如何优化查询性能?

sql-server execution-plan
  • 3 3 个回答
  • 2217 Views

3 个回答

  • Voted
  1. Best Answer
    Martin Smith
    2017-07-21T23:58:33+08:002017-07-21T23:58:33+08:00

    itemTimestamp 的数据类型是什么?该列是否已编入索引?该列是否可以为空?

    假设答案分别是datetime,是和否,您可能会考虑

    WHERE  a.itemTimestamp >= isnull(@timestamp_start, '17530101')
           AND a.itemTimestamp < isnull(@timestamp_end, '99991231') 
    

    如果您要更改datetime2并实际存储 1753 之前的日期,则需要将下限条件更改为00010101。这也不会带回与上限匹配的日期9999-12-31- 但在现实世界中,这不太可能导致问题。

    • 5
  2. Solomon Rutzky
    2017-07-21T22:10:08+08:002017-07-21T22:10:08+08:00

    是my_table.itemTimestamp实际DATE数据类型还是DATETIME?对于没有时间组件的数据类型,似乎是一个奇怪的列名;-)。如果它是 a DATETIME,那么第 1 步是为变量使用正确的数据类型。但是,如果它确实是一DATE列,请尝试以下查询。它打破了 4 种排列,以便 SQL Server 可以拥有简单、简洁的查询,而不是一个包含一堆OR通常使查询计划复杂化的 s 的全能查询。

    DECLARE @timestamp_start DATE = GETDATE() - 1;
    DECLARE @timestamp_end DATE = GETDATE();
    
    IF (@timestamp_start IS NULL AND @timestamp_end IS NULL)
    BEGIN
      SELECT   a.itemTimestamp AS [my_date]
      FROM     my_table a WITH (NOLOCK);
    END;
    ELSE
    BEGIN
      IF (@timestamp_start IS NOT NULL AND @timestamp_end IS NOT NULL)
      BEGIN
        SELECT   a.itemTimestamp AS [my_date]
        FROM     my_table a WITH (NOLOCK)
        WHERE    a.itemTimestamp >= @timestamp_start
        AND      a.itemTimestamp < @timestamp_end;
      END;
      ELSE
      BEGIN
        IF (@timestamp_start IS NULL)
        BEGIN
          SELECT   a.itemTimestamp AS [my_date]
          FROM     my_table a WITH (NOLOCK)
          WHERE    a.itemTimestamp < @timestamp_end;
        END;
        ELSE
        BEGIN
          SELECT   a.itemTimestamp AS [my_date]
          FROM     my_table a WITH (NOLOCK)
          WHERE    a.itemTimestamp >= @timestamp_start;
        END;
      END;
    END;
    
    • 1
  3. Ollie
    2017-07-22T05:16:15+08:002017-07-22T05:16:15+08:00

    只是为了扮演魔鬼的拥护者(在某些圈子里这是不赞成的),如果你确定你希望它使用那个索引并且它会改进事情,添加一个索引提示......只要记住你把它放在那里,如果你做出改变将来的索引或查询。添加:WITH (INDEX (###YOUR INDEX NAME HERE##))

    declare @timestamp_start date = getdate() - 1
    declare @timestamp_end date = getdate()
    
    SELECT  
        my_date = a.itemTimestamp
    FROM
        my_table a WITH (INDEX (###YOUR INDEX NAME HERE##))
    WHERE 
        (@timestamp_start is null OR a.itemTimestamp >= @timestamp_start)
        AND (@timestamp_end is null OR a.itemTimestamp < @timestamp_end)
    
    • 0

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve