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 / 问题 / 213896
Accepted
jesijesi
jesijesi
Asked: 2018-08-03 04:21:29 +0800 CST2018-08-03 04:21:29 +0800 CST 2018-08-03 04:21:29 +0800 CST

即使存在覆盖索引,也对分区表进行聚簇索引扫描

  • 772

我有一个基于 col1 int 分区的分区表。我还有一个覆盖索引,用于我正在尝试排除故障的查询。

https://www.brentozar.com/pastetheplan/?id=BkNrNdgHm

以上是方案

随心所欲,SQL Server 决定对整个表进行聚簇索引扫描,这显然很慢。如果我强制使用索引(如上面的计划),查询将快速运行。

SQL Server用什么神奇的逻辑来决定覆盖索引没有用?我不确定 top/orderby 和 rowgoal 是否与它有任何关系。

我的表结构是

Create table object2(col1 int, col3 datetime, col4 int, col5, col6 etc) clusterd on col1

nonclustered non aligned index is on col3,col4 (col1 is clustered so its included in nonclust)

SELECT top(?) Object1.Column1
    FROM Object2 Object1 WITH (NOLOCK,index(Column2))
    WHERE  Object1.Column3 >= ?
    AND Object1.Column4 IN (?)
    ORDER BY Object1.Column1

编辑添加的回购

    CREATE PARTITION FUNCTION [PFtest](int) AS RANGE RIGHT FOR VALUES (100000, 200000, 300000, 400000, 500000, 600000, 700000, 800000, 900000, 1000000)
    GO
    CREATE PARTITION SCHEME [PStest] AS PARTITION [PFtest] all TO ([PRIMARY]);
    GO

    create table test([ID] [int] IDENTITY(1,1) NOT NULL primary key clustered,[Created] [datetime] NULL,[Type] [int] NULL,text1 varchar(10),text2 varchar(20))
    on pstest(id)
    set nocount on

    declare @a int =1
    declare @type int
    while 1=1
    begin
    if @a%30 =0
    insert into test (Created, Type, text1, text2) select getdate(),4,'four','four'
    else
    insert into test (Created, Type, text1, text2) select getdate(),1,'one','one'
    set @a=@a+1
    end
    create nonclustered index ncl1 on test(created, type)

select min(created),max(created) from test
--2018-08-02 22:46:40.187   2018-08-02 22:49:01.577
SELECT top(10) ID
    FROM test  
    WHERE  Created >= '2018-08-02 22:49:01'
    AND Type IN (1, 4)
    ORDER BY ID -- clustered index scan

SELECT top(10) ID
    FROM test  
    WHERE  Created >= '2018-08-02 22:49:01.577'
    AND Type IN (1, 4)
    ORDER BY ID-- index seek of ncl1
sql-server sql-server-2014
  • 2 2 个回答
  • 820 Views

2 个回答

  • Voted
  1. Best Answer
    Paul White
    2018-08-03T04:31:57+08:002018-08-03T04:31:57+08:00

    是的,这很可能是行目标问题。

    SQL Server 评估扫描聚簇索引(以避免排序)?比在非聚簇索引中搜索匹配项、排序这些匹配项,然后返回顶部匹配项更快地找到第一个匹配项(此时扫描将停止)?。

    OPTION (QUERYTRACEON 4138)在您的 SQL Server 版本上,您可以通过运行查询以禁用行目标来测试设置行目标是否是原因。

    相关问答:

    • 为什么我的索引没有在 SELECT TOP 中使用?
    • TOP 如何(以及为什么)影响执行计划?
    • 为什么这个查询不使用我的非聚集索引,我该怎么做?
    • 6
  2. KumarHarsh
    2018-08-14T22:26:37+08:002018-08-14T22:26:37+08:00

    一般来说,最基本的术语是,如果成本Index scan小于,Index Seek则优化器可能会决定Index Scan。

    SELECT top(10) ID
        FROM test  
        WHERE  Created >= '2018-08-02 22:49:01'
        AND Type IN (1, 4)
        ORDER BY ID -- clustered index scan
    

    在这种情况下,有很多记录大于'2018-08-02 22:49:01' 并且只需要 10 条记录。

    所以如果优化器要从索引中检索记录,那么成本会更高。

    所以它Index Scan和这个“找到足够好的计划”

    SELECT top(10) ID
        FROM test  
        WHERE  Created >= '2018-08-02 22:49:01.577'
        AND Type IN (1, 4)
        ORDER BY ID-- index seek of ncl1
    

    这里有非常少的记录大于'2018-08-02 22:49:01.577'所以在这 10 条记录中是 Optimiser 想要的Index Seek。

    在这里您会注意到 Index Seek 运算符返回所有大于'2018-08-02 22:49:01.577'的行。实际行数是所有符合条件大于的行'2018-08-02 22:49:01.577'。然后排序运算符将其切片为 10。

    因此它可能不是“找到足够好的计划”。

    • 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