我在数据库中定义了以下表格
购物表
城市表
国家/地区表
REGION
ShopImages
这是我的选择查询
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条记录和商店有 40,000,000 +条记录。
获取记录需要时间。已定义所有聚簇索引(主键)。
我正在尝试在DTA(数据库调优顾问)的帮助下进行优化。 它建议我添加以下索引
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中获取所有的建议吗?它还建议增加一些统计数据。
如何更好地改进我的上述查询?
答案 0 :(得分:2)
在分析索引时很难说DTA是错误的,因为我不知道数据的分布情况,但是我在主键之外添加的第一个索引是SHOP.CityID
和SHOP.Active
上的(可能是复合的)索引。
如果没有测试,我不能给你任何绝对,但这就是推理。
由于您基本上是在SHOP
上进行过滤并且在任何其他表上都没有过滤器,因此查询的繁重工作很可能是在SHOP
中过滤50M行。
如果数据库从任何其他表开始加入,则未经过滤的连接将导致针对CITY
的3M行,并且从过滤SHOP
开始将极有可能导致更少的数量。编译器喜欢“少”,这是有充分理由的。
这是SHOP
;
WHERE S.Banner like '%restaurant%' OR S.Description like '%restaurant%'
AND S.CityId=10 AND S.Active=1
由于以LIKE
为基础的%
查询基本上无法使用索引,因此您需要尽可能简单快速地过滤{{1} }。如果你索引那些,其他两个条件将不需要扫描超过使用索引找到的几行而不是扫描 - 可能 - 50M行。
我可以看到索引建议的唯一原因不仅仅是一个小的影响,如果S.CityId=10 AND S.Active=1
表有大量的字段,索引将允许数据库从磁盘读取更少的数据到达田野。不是说情况,但只是尝试它肯定会说明。
答案 1 :(得分:1)
在某些情况下,您可能需要重新考虑在主键列上使用聚簇索引。
例如,如果您通常搜索特定城市中的商店(如果示例查询是“典型查询”就是这种情况),那么将Shop聚集在CityId上可能是非常有益的(以便所有商店都在给定的城市组合在一起)