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 / 问题 / 188943
Accepted
Pieter Geerkens
Pieter Geerkens
Asked: 2017-10-21 09:05:01 +0800 CST2017-10-21 09:05:01 +0800 CST 2017-10-21 09:05:01 +0800 CST

为什么索引视图的性能比等效表差得多?

  • 772

我有这张桌子

create table SkaData.FiscalPeriod(
     PeriodNo               int     not null constraint FiscalPeriod_FK_BasePeriod    references SkaData.Period(Number)
    ,YearEndMonthNo         int     not null constraint Fiscalperiod_CK_YearEnd       check (YearEndMonthNo between 1 and 12)
    ,ContributionType       char(4) not null constraint FiscalPeriod_CK_ContribType   check(ContributionType in ('Base','Cr','Dr'))

    ,ContributionSign       int     not null constraint FiscalPeriod_CK_ContribSign   check(ContributionSign in (+1,-1))
    ,ContributionPeriodNo   int     not null constraint FiscalPeriod_FK_ContribPeriod references SkaData.Period(Number)

    ,constraint FiscalPeriod_PK unique clustered (PeriodNo,YearEndMonthNo,ContributionType)
);

目前填充为

    insert Skadata.FiscalPeriod(
        PeriodNo,YearEndMonthNo,ContributionType,ContributionperiodNo,ContributionSign)
        select
             data.PeriodNo
            ,YearEndMonthNo
            ,ContributionType
            ,ContributionPeriodNo   = pvt.PeriodNo
            ,ContributionSign       = pvt.Sign
        from (
            select 
                 YearEndMonthNo = N
                ,PeriodNo       = Period.Number
                ,CreditPeriodNo = Period.Number - MonthNo
                ,DebitPeriodNo  = Period.Number - MonthNo + N - 12
            from SkaData.Period
            join (select * from 
                (values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12) )Number(N)
            )Number(N)  on Number.N >= MonthNo + 12 - Period.Number
        ) data
        cross apply (values
             (PeriodNo,         +1, 0,  'Base')
            ,(CreditPeriodNo,   +1, 12, 'Cr')
            ,(DebitPeriodNo,    -1, 12, 'Dr')
        ) pvt(PeriodNo, Sign, TestPeriod,ContributionType)
        where YearEndMonthNo   <> pvt.TestPeriod

这允许从日历 YTD 值轻松转换为非日历 YTD 值。

然而,该表是一个派生表,这意味着它必须在实例化新年份时进行维护。我想用索引视图替换它以消除这种维护的需要。

我已经使用 NUMBERS 表证明了上面的 select 与下面的 select 的等价性,它是精确和确定的,不使用子查询或 APPLY 运算符,允许它成为索引视图的定义:

create view SkaData.FiscalPeriod with schemabinding as
    select
         PeriodNo               = cast(Period.Number as int)
        ,YearEndMonthNo         = cast(months.N/3 + 1 as int)
        ,ContributionType       = cast(case months.N%3 when 0 then 'Base'
                                                       when 1 then 'Cr'
                                                       when 2 then 'Dr'
                                  end as char(4))
        ,ContributionPeriodNo   = cast(case months.N%3 when 0 then Period.Number
                                                       when 1 then Period.Number - MonthNo
                                                       when 2 then Period.Number - MonthNo + (months.N/3) + 1 - 12
                                  end as int)
        ,ContributionSign       = cast(case months.N%3 when 0 then +1
                                                       when 1 then +1
                                                       when 2 then -1
                                  end as int)
    from SkaData.Period
    join SkaData.Number months   on (months.N/3) + 1 >= MonthNo + 12 - Period.Number
                                and months.N between 0 and 33
go

create unique clustered index FiscalPeriod_PK on SkaData.FiscalPeriod(PeriodNo,YearEndMonthNo,ContributionType);
go

请注意,视图上的单个聚集索引与原始表上的(唯一的)聚集索引相同。

但是,针对索引视图运行的几个查询比针对原始表运行得更慢(平均大约 3*,最多大约 6*,更慢)。

有谁知道为什么会发生这种情况?引擎中可能存在错误,无法相同地处理两个相同的聚簇索引吗?我的测试数据目前只涵盖两个时期,相隔一年。

我最初认为这可能是由于视图的列可以为空,但使用isnull合并它们只会使查询变得如此缓慢,我什至无法衡量性能。

我在 SQL Server 2014 上:

Microsoft SQL Server 2014 (SP2-GDR) (KB4019093) - 12.0.5207.0 (Intel X86) 
    Jul  3 2017 02:37:05 
    Copyright (c) Microsoft Corporation
    Developer Edition on Windows NT 6.1 <X64> (Build 7601: ) (WOW64)
sql-server sql-server-2014
  • 1 1 个回答
  • 96 Views

1 个回答

  • Voted
  1. Best Answer
    Steven Hibble
    2017-10-21T09:38:42+08:002017-10-21T09:38:42+08:00

    索引视图通常不能用作表的直接替代品。原因是WITH (NOEXPAND)经常需要提示。通常,视图会被扩展(尽管有索引)并使用底层定义。Paul White之前已经写过关于它的文章。

    更改查询来自: SELECT * FROM SkaData.FiscalPeriod

    至: SELECT * FROM SkaData.FiscalPeriod WITH(NOEXPAND)

    • 6

相关问题

  • 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