在这种情况下将使用哪个索引?


11

SQL Server 2014标准版

我需要找到特定月份往返特定城市的航班数量。例如

select count(*) 
from flights 
where flightTo_AirportCode = 'aaaa' 
and flightFrom_Airportcode = 'bbbb' 
and flightdate < '2016-04-01' 
and flightdate > '2016-02-28' ;

表模式如下。

我正在尝试评估索引模型A或索引模型B(如下)是否更可取(建立索引需要花费数小时,并且磁盘空间一次只能存在一个,因此我想在跳之前先进行研究)。

根据我的经验,任何一个索引都可以。我对吗?

  create index [modelA] on flights (flightTo_AirportCode, flightFrom_AirportCode, flightDate)

  create index [modelB] on flights (flightDate, flightTo_AirportCode, flightFrom_AirportCode)

(或者,更好的是,我可以使用二进制索引或高级机制来解决这个问题吗?)

CREATE TABLE [dbo].[flights](
    [flightId] [uniqueidentifier] NOT NULL,
    [accountId] [uniqueidentifier] NULL,
    [flightDate] [datetime] NULL,
    [flightTo_AirportCode] [nvarchar](30) NULL,
    [flightFrom_AirportCode] [nvarchar](30) NULL,
    -- ... 45 more fields
    CONSTRAINT [PK_flight] PRIMARY KEY CLUSTERED 
(
    [flightId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 70) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

Answers:


18

对于此查询,索引A更好。如果WHEREIN列中使用范围条件或运算符的条件之外的所有条件都是相等性检查,则最后一个列应在所有具有相等性检查的列之后,位于索引的最后。

这使优化器可以使用索引查找到与条件匹配的第一行,然后遍历索引,直到找到与之不匹配的行。中间的所有行也是匹配项。

因此,此查询的最佳索引是(to, from, date)(您的模型A)或(from, to, date)

模型B索引的日期优先,因此它不是最佳日期,尽管它仍是查询的覆盖索引。如果使用此选项,则查询计划将几乎相同。索引试图找到与范围条件(date > '2016-02-28')相匹配的第一行,然后遍历索引直到找到与范围条件()不符的行date < '2016-04-01'。但是中间的所有行不一定都符合其他两个条件,因此必须对照这些条件进行检查,并且(可能有很多)被拒绝。

因此,尽管计划是相似的,但是模型A计划只需要遍历索引中包含所有需要的行的部分,只有它们,而模型B计划则要遍历索引中(可能很多)的大部分。指数。


  • 对于日期(YYYYMMDD),最好使用100%安全的格式。

  • 并且,如果您想确定三月的日期,则应使用包含独占的检查:

    AND flightdate >= '20160301' AND flightdate < '20160401' 

    保证可以使用日期和日期时间类型。您当前的查询还将包括具有与我认为您不希望'2016-02-28'的时间不同的行'00:00:00'(您可以保证没有任何时间)。包含式-排除式方法也可以在leap年中使用(提醒您2016年为a年,因此查询也将返回2月29日)。

另请参阅Aaron Bertrand的这些博客文章:

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.