我刚刚阅读this blog post,简而言之,它说如果SQL服务器在构建查询计划方面做得不够好,那么你要做的最后一件事就是开始硬编码。所以,这让我思考;没有硬编码的东西你怎么能“硬编码”东西。 (是的,这就是我倾向于思考的方式。)
以下是否; 1)可能,2)一个好主意和3)是否有任何工具可以帮助DBA做到这一点?
您的查询速度很慢,并且由于某种原因您不喜欢DBMS选择的查询计划。所以你开始玩它(在开发服务器上)强迫不同的东西,直到你得到一个更好的计划。然后你尝试分解DBMS的决策过程,找出为什么它没有选择那个,然后反向工程,以便让它选择更好的。
编辑:第一个答案似乎回答的问题与我试图提出的问题略有不同。
情况:您的查询速度不够快,但您认为通过对查询计划的部分内容进行硬编码可以使查询速度更快(此时)。但是,出于各种原因,你不想在prod中这样做。
(建议)解决方案:构建并测试硬编码查询计划。当你发现一个足够快的时候,当它选择不使用更好的计划时,尝试并退出DBMS正在查看的内容(统计数据等)。完成后,将其作为调整内容的指南。
问题:以上是一种实用的方法吗?是否有足够的旋钮使其工作?他们的任何工具是否显示数据用于制定查询计划决策?
答案 0 :(得分:3)
首先,正如评论者指出你链接的帖子,这里有一些FUD - 总结那些不想点击链接的人:“事情可能会变坏。 ..买我的书!“
您在问题中列出的内容不是硬编码,而是使用硬编码来确定使用数据库的最佳方法。这对我来说似乎没问题。只要你不在那里留下硬编码提示,事情应该没问题,SQL服务器仍然可以随着数据的变化而改变优化。
答案 1 :(得分:3)
This Microsoft Support page指向如何创建仅限统计数据库。不担心撕裂任何东西,但使用当前的索引统计数据能够进行一些查询计划分析。这可能有所帮助。
答案 2 :(得分:2)
您可以在查询中对索引名称和优化提示进行硬编码。
这是一个转换的查询和一个可能的转换
SELECT Customers.CompanyName, Sum (Orders.TotalAmount) As TotalAmount
FROM Customers
INNER JOIN Orders
ON Customers.ID = Orders.CustomerID
WHERE Customer.Country IN ('USA', 'Canada')
现在提供硬编码提示
SELECT Customers.CompanyName, Sum (Orders.TotalAmount) As TotalAmount
FROM Customers WITH (NOLOCK, IdxCountry)
INNER LOOP JOIN Orders (TABLOCK, IdxCustomerOrders)
ON Customers.ID = Orders.CustomerID
WHERE Customer.Country IN ('USA', 'Canada')
第二个查询强制执行计划使用以下
你可以软编码索引和加入提示吗?不作为常规查询的一部分。但是,您可以为此目的构建和执行动态SQL。
SQL Server非常擅长查询优化,您阅读的内容越多,您编写的查询就越多。我认为您应该阅读查询优化和索引优化以更好地理解
What are your most common sql optimizations?
How can I learn SQL Server index tuning?
回答你的问题
答案 3 :(得分:2)
如果优化器选择了您不期望的计划,则通常表明底层数据结构未正确形成。索引可能会丢失。您可能正尝试跨两个具有不同数据类型的列进行连接。您可能正在搜索或加入复杂的生成列。我以前见过这样的东西:
SELECT *
FROM
t1
INNER JOIN t2 ON LTRIM(RTRIM(t1.code)) = LTRIM(RTRIM(t2.code))
这迫切希望改进基础数据结构!
答案 4 :(得分:2)
您要求的事实(在大多数情况下,除了您之外,我确定)表明您没有足够的SQL Server经验,无法很好地对优化程序进行微观管理。我和我知道的SQL Server向导(其中有几个人这样做非常有效 - 但总是在边缘情况下,根据我的经验)会说你最终会发现一个更好的方法来编写你的查询,你的提示不会真正有用。但YMMV像往常一样。
我会花时间重新构思我的查询和查询计划。并且寻找我们都知道的其他事情,但有时忘记检查这也可能导致意外,例如统计数据是否是最新的,以及我们是否正在测试足够准确的代表性数据。
提示和锁定模式是人们在开始耗尽其他想法时可能开始搞得太快的两个调整。对于优化器,特别重要的是要知道“为什么”你所期待的不会发生,并且“为什么”你所做的改变会导致你观察到的效果。
答案 5 :(得分:0)
是的,你应该弄清楚为什么它提出了次优计划。这不应该是命中或错过。您应该手动找出最佳计划,查找差异,然后查找原因。计划错误的原因是无效基数计算。歪斜会杀了你。
**这就是你在Oracle中的表现,你可以告诉我SQL Server如何使用绑定变量**
假设列上有“是/否”列和索引,因为它在where子句中频繁出现。在10000行中,一行是肯定的,另外99.99%的行是否。
如果使用绑定变量编写查询,如下所示:( SS中的参数化查询)
SELECT * FROM table WHERE yn_col =:1
优化器无法为此查询缓存单个计划。如果你要求是,那么索引是合适的,FTS也不会太糟糕。如果你要求No,那么FTS是合适的,但是通过row-id进行表访问的索引扫描将是一场噩梦。
你有两个选择,在FTS修复计划,这样总是在同一时间。对于最终用户,它看起来是一致的。但是如果你想利用索引,你需要将它写成两个查询而不对其进行参数化,以便优化器将其视为“是”和“否”,如果列值上有直方图,则基数将被正确计算。
除非SQL Server能够像Oracle在11g中添加的那样缓存绑定变量敏感计划,否则此处没有其他选择。