【发布时间】:2014-03-02 19:05:54
【问题描述】:
我有一个 SQL Azure 数据库,其中一张表包含超过 40 万个对象。此表中的一列是对象下载次数的计数。
我有几个查询包括这个特定的列(称为timesdownloaded),按降序排序,以便找到结果。
这是 LINQ to SQL 中的示例查询(我在 C# .NET 中编写所有这些):
var query = from t in db.tablename
where t.textcolumn.StartsWith(searchfield)
orderby t.timesdownloaded descending
select t.textcolumn;
// grab the first 5
var items = query.Take(5);
这个查询平均每分钟调用 90 次。
平均每分钟可能会下载 10 次对象,因此 timesdownloaded 列的更新频率很高。
您可以想象,任何涉及timesdownloaded 列的索引都会在几个小时内产生超过 30% 的碎片。我已经实施了一个索引维护计划,每隔几个小时检查和重建这些索引。这会有所帮助,但是当我希望避免或最小化重建索引时,当然会增加查询响应时间的峰值。
我尝试了多种索引方案。
表现最好的索引覆盖了同时包含textcolumn 和timesdownloaded 列的索引。重建这些索引后,查询速度当然快得惊人。
但是,这些索引碎片严重,由于重建索引和其他我不了解的因素,我最终会出现相当频繁的延迟峰值。
我也尝试过不索引timesdownloaded 列。这似乎在整体上表现得更加一致,尽管当然速度较慢。当我检查 SQL 查询执行计划时,SQL 尝试优化此查询的方式似乎非常不一致。当然,它以逻辑读取日志结束,因为它必须从表中获取timesdownloaded 列,而不是有组织的索引。所以这不是最优的。
我想弄清楚的是,我是否从根本上遗漏了我配置或管理此数据库的方式。
我不是 SQL 专家,我还没有找到如何做到这一点的好答案。
我看到了一些存储过程可以提供帮助的建议,但我不明白为什么,也没有尝试让这些建议与 LINQ 一起使用。
如下所述,我考虑过缓存,但还没有采取这一步。
在某些情况下,此查询是搜索建议功能的一部分。所以它经常被许多不同的搜索词调用。
任何建议将不胜感激!
【问题讨论】:
-
您只需要 Take(5) 还是您还需要更深入地查询表格?否则缓存前 5 名将是一个解决方案
-
在这个例子中,我只选择了前 5 名。在本专栏的其他查询中,我需要更深入。
-
我仍然会将 topX 缓存在内存或另一个表/索引视图中,然后转到该表...
-
对于 400k 的对象,每分钟 10 次更新和每分钟 90 次查询,您的索引需要重建是正常的,如果不是,查询速度很慢。我建议您将更新(下载)存储在单独的表中并定期更新真实表以尽量减少更新次数,以便尽可能长时间地将更新与读取分开。例如,当数据库工作负载最低时,您可以每天更新一次表。但是,在您的情况下,当然需要任何形式的缓存。
-
感谢您的建议。
标签: sql .net performance linq-to-sql azure-sql-database