3

我在数据库中定义了以下表

商店表

  • 店铺编号
  • 店铺名称
  • 所有者
  • 横幅
  • 标题
  • 城市编号
  • ShopImageId
  • 积极的

城市表

  • 城市编号
  • 城市名称
  • 国家 ID
  • 区域 ID

国家表

  • 国家 ID
  • 国家的名字
  • 区域 ID

地区

  • 区域 ID
  • 区域名称

商店图片

  • ID
  • 图片
  • 店铺编号

这是我的选择查询

SELECT ShopName, Owner, CityName, CountryName,RegionName
FROM Shop S 
INNER JOIN City CT ON CT.CityId=S.CityId
INNER JOIN Country CO ON CO.CountryId=CT.CountryId
INNER JOIN Region R ON CT.RegionId=R.RegionId
LEFT OUTER JOIN ShopImages SI ON S.ShopImageId=SI.Id

WHERE S.Banner like '%restaurant%' OR S.Description like '%restaurant%'
AND S.CityId=10 AND S.Active=1

截至目前,城市表有大约 3,000,000 条记录,而 Shop 有 40,000,000 多条记录。

获取记录需要时间。所有聚集索引(主键)都已定义。

我正在尝试在 DTA(Database Tuning Advisor)的帮助下进行优化。它建议我添加以下索引

CREATE NONCLUSTERED INDEX 
  [_dta_index_CITY_9_2098106515__K9_K20_K1_K2] ON [dbo].[CITY] 
(
    [COUNTRYID] ASC,
    [REGIONID] ASC,
    [CITYID] ASC,
    [CITYNAME] ASC
)WITH (SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF) 
  ON [PRIMARY]

是否值得添加此索引?我可以接受 DTA 的所有建议吗?它还建议添加一些统计信息。

如何更好地改进我的上述查询?

4

2 回答 2

2

在分析索引时很难说 DTA 是错误的,因为我不知道数据分布而且确实如此,但我要添加的第一个索引超出主键是和上的(可能是复合的)SHOP.CityID索引SHOP.Active

我不能在没有测试的情况下给你任何绝对的东西,但这就是推理。

由于您基本上是在SHOP对任何其他表进行过滤并且没有过滤器,因此查询的繁重工作很可能是在过滤SHOP.

如果数据库从任何其他表开始加入,未过滤的连接将导致 3M 行反对CITY,并且从过滤开始SHOP很可能会导致少得多。编译器喜欢“更少”是有充分理由的。

这是过滤器SHOP

WHERE S.Banner like '%restaurant%' OR S.Description like '%restaurant%'
  AND S.CityId=10 AND S.Active=1

由于LIKE%. _ _ S.CityId=10 AND S.Active=1_ 如果您对它们进行索引,则其他两个条件不需要扫描超过使用索引找到的几行而不是扫描 - 可能 - 50M 行。

我可以看到建议的索引影响不大的唯一原因是,如果CITY表具有大量字段,并且索引将允许数据库从磁盘读取更少的数据以获取字段。不是说是这样,但只有尝试才能确定。

于 2013-02-23T14:34:16.710 回答
1

在某些情况下,您可能需要重新考虑在主键列上设置聚集索引。

例如,如果您通常搜索给定城市中的商店(如果示例查询是“典型查询”就是这种情况),将 Shop 聚集在 CityId 上可能非常有益(这样给定城市中的所有商店被组合在一起)

于 2013-02-23T15:06:21.673 回答