【问题标题】:How would you optimize this SQL Server 2008 R2 Table您将如何优化此 SQL Server 2008 R2 表
【发布时间】:2011-11-08 01:35:07
【问题描述】:

我的浏览器游戏有一个私人消息系统。当我使用查询检查大多数 CPU 时间时,我发现该表是使用 CPU 最多的表。我不擅长索引,查询时间优化。因此,我想获得有关此表的优化提示。

好的,现在我将首先向您展示表结构:

结构图

好吧,下面这个查询会读取用户有多少未读消息,这个查询是使用 CPU 最多的查询,因为它会在每次页面加载时读取:

SELECT COUNT([Id]) [Number] 
FROM [MyTable] 
WHERE [ReceiverUserId] = @1 
  AND [ReceiverReaded] = @2 
  AND [ReceiverDeleted] = @3

那么什么样的索引等可以提高我的性能?

【问题讨论】:

    标签: sql-server performance optimization


    【解决方案1】:

    为什么要在这些列上允许 NULL——无论它是否被读取。只需默认为 0。然后在 Read/Deleted/ReceivedUser 上进行索引(如果您需要大量 ALL READ 访问权限,则按此顺序将它们“分区”,或者,如果大多数读取仅针对单个用户,请在 ReceivedUser 上放置索引)

    您想要做的是看到您的索引被覆盖。在您的情况下,您可以在 ReceiverUserId 和 INCLUDE 列 ReceiverReaded 和 ReceiverDeleted 上放置一个索引,它将覆盖(针对该查询)。在执行计划中,您应该只看到一次索引搜索,因为您只有一个用户。

    您可以捕获工作负载,然后通过 SQL Server 中的索引调整向导运行它,它可能会提出非常好的建议。当然,您需要解释它告诉您的内容。

    【讨论】:

    • 感谢您的回答。实际上它们的默认值是 0 所以永远不会为空。关于索引调优向导有什么好的参考吗?
    • @MonsterMMORPG 在“工具”菜单上 - 您可以只调整窗口中的特定查询,也可以使用探查器捕获跟踪,然后使用数据库引擎优化顾问为您提供建议整个工作量。
    【解决方案2】:

    您总是希望在要搜索的字段上建立索引,因此您可能会通过在 [ReceiverUserId]、[ReceiverReaded] 和 [ReceiverDeleted] 上添加索引来提高查询性能。

    当然,索引的列越多,更新和插入的速度就越慢。

    【讨论】:

    • 我要添加 3 个不同的索引吗?
    • 这完全取决于您将针对此表运行的其他查询。例如,如果您有另一个仅查看 ReceiverReaded 的查询,则可以使用 3 个单独的索引。
    • 如果我没有那只看起来 ReceiverReaded 我应该如何制作索引?
    • 在这种情况下,我同意@Cade 上面的回答,只需按照您拥有它们的顺序创建一个包含所有 3 列的索引。
    • 例如这行得通吗?创建非集群索引 [_dta_index_MyTable_8_1547868581__K6_K3_K5] ON [dbo].[MyTable] ( [ReceiverReaded] ASC, [ReceiverUserId] ASC, [ReceiverDeleted] ASC )WITH (SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF) ON [主要]
    【解决方案3】:

    数据库优化中一个相当简单的经验法则是索引作为谓词一部分出现在 WHERE 子句或 JOIN 中的任何列。从您的示例中,这些将包括:

    • ReceiverUserId
    • ReceiverReaded
    • 接收方已删除

    还有许多可用的优化器工具可以“观察”您的数据库并告诉您要索引哪些列以获得最佳性能。

    【讨论】:

    • 查看前三个链接:google.com/… 我个人喜欢 RedGate 的 SQ Server 产品,但还有其他选择。
    【解决方案4】:

    可能对您的应用程序可行的不同方法:当用户没有明确请求任何内容时,根本不要查询消息表,例如当他不在您游戏的“消息”部分时。

    尝试使用整数值列扩展您的用户表,以指示有多少消息以及已读取多少消息。每次修改消息表的同时,也修改了用户表中对应的值。

    这样您就无需在每次刷新时查看整个表格。但请注意,这种方法的低迷是程序员方面的一些额外同步工作。如果你已经正确封装了消息表的修改(添加消息、读取消息、删除消息),这应该不是问题。

    【讨论】:

    • 其实这是最好的主意 :) 我能做到。这将需要更多的编码时间,但由于这是最消耗 cpu 的查询,因此值得 ^^
    • 我看不出这如何提高整体性能。它可能会提高这一查询的速度......但只是以减慢您对消息表的写入速度为代价。
    • @kuru kuru pa:它提高了整体性能,因为在每次刷新时都会在游戏的每个页面上执行查询。改进的程序逻辑应该总是比过早的低级查询优化更受青睐。顺便说一句:在这种情况下,发布/阅读/删除消息的速度可以忽略不计,因为它只是增加/减少一个 int。
    【解决方案5】:
    1. 为您的搜索字段编制索引(根据@PaulStock 的回答)。
    2. 将 tinyint 字段更改为位字段(默认值 = 0)
    3. 您的身体真的需要 nvarchar(4000) 吗?这是巨大的!考虑更短的消息(例如 nvarchar(300) 或更小 - 作为参考,Twitter 只有 140。)

    【讨论】:

    • 将它们更改为 bit 从来没有出现在我的脑海中是个好主意:D 我不认为消息列确实会影响此查询性能,因为我不寻求它。
    • 大小很重要...:-)...对于您列出的特定查询,它可能不会有太大区别(它仍然在虚拟表 1 中),但您提到调整其他查询——如果他们中的任何一个选择了正文,如果你可以缩小字段,你应该会看到改进。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-12
    • 1970-01-01
    • 2011-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多