您好希望有人可以帮助我的SQL理论。我必须创建一组使用来自多个表的连接的报告。这些报告的运行速度远远低于我想要的速度,我希望能够优化我的SQL,尽管我的知识已经碰壁,我似乎无法在Google上找到任何东西。
我希望有人可以给我一些最佳实践指导。
基本上我试图过滤结果集,因为它回来减少后面连接中包含的行数
Items INNER JOIN BlueItems ON Items.ItemID = BlueItems.ItemID AND BlueItems.shape = 'square'
LEFT JOIN ItemHistory ON Items.ItemID = ItemHistory.ItemsID
LEFT JOIN ItemDates ON Items.ItemID = ItemDates.ItemID
WHERE ItemDates.ManufactureDate BETWEEN '01/01/2017' AND '01/05/2017'
我认为,对于正方形的蓝色物品,内部连接会大大减少此时的数据集?
我也明白Where子句足够智能,可以减少运行时的数据集?我错了吗?它是返回所有数据然后只是过滤该数据?
关于如何加速这种查询的任何指导都很棒,索引等等已经落实到位。不幸的是,数据库实际上是由其他人照看的,我只是根据他们的数据库创建报告。这确实限制了我能够优化我的查询而不是数据本身。
我想在这一点上我有时间尝试提高我对SQL处理各种方法的知识,这些方法可以过滤数据并尝试了解哪些方法实际上减少了所使用的数据集,哪些只是对其进行过滤。任何指导都将非常感谢!
答案 0 :(得分:0)
您提到主键都已编入索引,但主键字段始终如此。您当前查询中唯一可能从中受益的部分是第一次加入Items
。对于其他连接和WHERE
子句,未使用这些主键字段。
对于此特定查询,我建议使用以下索引:
ALTER TABLE BlueItems ADD INDEX bi_item_idx (ItemID, shape)
ALTER TABLE ItemHistory ADD INDEX ih_item_idx (ItemID)
ALTER TABLE ItemDates ADD INDEX id_idx (ItemID, ManufactureDate)
对于ItemHistory
表,索引ih_item_idx
应该加速涉及ItemID
外键的连接。同名的列也与其他两个连接有关,因此是其他索引的一部分。复合索引(即索引涉及多个列)的原因是我们希望覆盖连接或WHERE
子句中出现的所有列。
答案 1 :(得分:0)
这些评论不是一个真正的答案,但太大了,无法发表评论......
如果日期作为参数传递(我猜测它们是),那么它可能是引起问题的参数嗅探。查询可能使用错误的计划。
我在使用between
运算符时特别看到了这一点。在查询结尾添加OPTION(RECOMPILE)
时,可以尝试一些简单的方法。这可能看起来反直觉但只是尝试一下。虽然编译的查询应该比重新编译更快,但如果使用了错误的计划,它可能会减慢速度。
此外,如果ItemDates很大,请尝试将yuor过滤后的结果转储到临时表并加入到该表中,如下所示。
SELECT * INTO #id FROM ItemDates i WHERE i.ManufactureDate BETWEEN '01/01/2017' AND '01/05/2017'
主要查询的更改类似于
SELECT *
FROM Items
JOIN BlueItems ON Items.ItemID = BlueItems.ItemID AND BlueItems.shape = 'square'
JOIN #id i ON Items.ItemID = i.ItemID
LEFT JOIN ItemHistory ON Items.ItemID = ItemHistory.ItemsID
我还将JOIN从LEFT JOIN
更改为JOIN
(隐式内连接),因为您只选择ItemDates
匹配的项目{{1}加入毫无意义。