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 / 问题 / 72726
Accepted
Vojtěch Dohnal
Vojtěch Dohnal
Asked: 2014-07-31 02:37:32 +0800 CST2014-07-31 02:37:32 +0800 CST 2014-07-31 02:37:32 +0800 CST

与单独的 SELECT 相比,使用 OR 条件的索引查找要慢得多

  • 772

基于这些问题和给出的答案:

SQL 2008 Server - 性能损失可能与非常大的表有关

具有历史数据的大型表分配了过多的 SQL Server 2008 Std。内存 - 其他数据库的性能损失

我在数据库 SupervisionP 中有一个表,定义如下:

CREATE TABLE [dbo].[PenData](
    [IDUkazatel] [smallint] NOT NULL,
    [Cas] [datetime2](0) NOT NULL,
    [Hodnota] [real] NULL,
    [HodnotaMax] [real] NULL,
    [HodnotaMin] [real] NULL,
 CONSTRAINT [PK_Data] PRIMARY KEY CLUSTERED 
(
    [IDUkazatel] ASC,
    [Cas] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

ALTER TABLE [dbo].[PenData]  WITH NOCHECK ADD  CONSTRAINT [FK_Data_Ukazatel] FOREIGN KEY([IDUkazatel])
REFERENCES [dbo].[Ukazatel] ([IDUkazatel])

ALTER TABLE [dbo].[PenData] CHECK CONSTRAINT [FK_Data_Ukazatel]

它包含 cca 2.11 亿行。

我运行以下语句:

DECLARE @t1 DATETIME;
DECLARE @t2 DATETIME;

SET @t1 = GETDATE();
SELECT min(cas) from PenData p WHERE IDUkazatel=24
SELECT min(cas) from PenData p WHERE IDUkazatel=25
SET @t2 = GETDATE();
SELECT DATEDIFF(millisecond,@t1,@t2) AS elapsed_ms;


SET @t1 = GETDATE();
SELECT min(cas) from PenData p WHERE IDUkazatel=24 OR IDUkazatel=25 
SET @t2 = GETDATE();
SELECT DATEDIFF(millisecond,@t1,@t2) AS elapsed_ms;

结果显示在这里:

执行计划

第三个 SELECT 还将更多数据加载到 SQL Server 内存缓存中。

为什么第三个 SELECT 比前两个 SELECT(16 毫秒)慢得多(8.5 秒)?如何使用 OR 提高第三个选择的性能?我想运行以下 SQL 命令,但在我看来,在这种情况下,创建游标和运行单独的查询比单个选择要快得多。

 SELECT MIN(cas) from PenData p WHERE IDUkazatel IN (SELECT IDUkazatel FROM  ...)

编辑

正如大卫建议的那样,我将鼠标悬停在粗箭头上:

肥箭

sql-server sql-server-2008
  • 1 1 个回答
  • 6734 Views

1 个回答

  • Voted
  1. Best Answer
    David Spillett
    2014-07-31T03:19:56+08:002014-07-31T03:19:56+08:00

    对于前两个查询,它所要做的就是在聚集索引中扫描该值的第一个条目IDUkazatel- 因为索引的顺序,该行将是该值的 cas 的最低值IDUkazatel。

    在第二个查询中,此优化不是价值,它可能正在寻找第一行,IDUkazatel=24然后向下扫描索引直到最后一行,以找到所有这些行IDUkazatel=25的最小值。cas

    如果您将鼠标悬停在那个粗箭头上,您会看到它正在读取许多行(当然是所有 24 行,也可能是所有 25 行),而其他两个的计划输出中的细箭头显示top导致它仅考虑一行。

    您可以尝试运行每个查询,然后获取找到的最小值的最小值:

    SELECT MIN(cas)
    FROM   (
            SELECT cas=MIN(cas) FROM PenData p WHERE p.IDUkazatel = 24
            UNION ALL
            SELECT cas=MIN(cas) FROM PenData p WHERE p.IDUkazatel = 25
        ) AS minimums
    

    也就是说,您似乎有一个包含IDUkazatel值而不是显式OR子句的表。下面的代码将使用这种安排,只需将表名替换为@T包含IDUkazatel值的表名:

    SELECT 
        MinCas = MIN(CA.PartialMinimum)
    FROM @T AS T
    CROSS APPLY 
    (
        SELECT 
            PartialMinimum = MIN(PD.Cas)
        FROM dbo.PenData AS PD
        WHERE 
            PD.IDUkazatel = T.IDUkazatel
    ) AS CA;
    

    在理想情况下,SQL Server 查询优化器会为您执行此重写,但现在并不总是考虑此选项。

    • 11

相关问题

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

  • 我在索引上放了多少“填充”?

  • 是否有开发人员遵循数据库更改的“最佳实践”类型流程?

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

  • 从 SQL Server 2008 降级到 2005

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