加速从大表读取的方法

时间:2013-06-22 07:30:09

标签: sql sql-server select sql-server-2008-r2

我尝试记录SQL中的所有内容,因此请考虑添加一个名为log的表并添加其中的所有内容,log表是:

  • ID UNIQUEIDENTIFIER - PK
  • LogDate DATETIME PK
  • IP NVARCHAR
  • Action NVARCHAR
  • Info XML
  • UniqueID BIGINT

我记录了以下所有内容:登录,检查权限,查看页面,访问对象和..到此表

然后我想还需要一些 Log-Restore 实现,所以有些日志记录是可恢复的,有些则没有,Log表有大约8百万条记录,但是可恢复的记录大约有20万,所以每次我们需要恢复,需要选择8百万,然后我决定添加新的表和添加可恢复的日志 到这个新表:log_restore

  • ID UNIQUEIDENTIFIER
  • LogDate DATETIME
  • IP NVARCHAR
  • Action NVARCHAR
  • Info XML
  • UniqueID BIGINT - PK

我需要时可以记录每件事情。

但是当我需要查看日志时:该过程从log表中获取所有记录,并将它们与log_restore表合并(联合)。

所以我需要加速这个程序对插入没有影响(意味着不要慢),这是我的想法:

  1. 将记录添加到log_restore时也将其添加到log表中(因此选择不需要联合)

  2. 使用此选择命令创建视图

  3. 添加简单数据类型列而不是XML

  4. 在简单数据类型列上添加群集PK,如BIGINT

  5. 你有什么想法?有什么建议吗?

4 个答案:

答案 0 :(得分:6)

一般来说,应尽量使用尽可能少的空间;它有助于在执行查询时减少磁盘搜索。并且比较较小的数据类型总是需要更少的时间!

可以对列进行以下调整:

  • 使用不可为空的列(减少存储空间,减少测试次数)
  • 以时间戳的形式存储LogDate(UNSIGNED INT,4个字节)而不是DATETIME(8个字节)
  • IP地址不应存储为NVARCHAR;如果要存储IPv4地址,则4个字节就足够了(BINARY(4))。 IPv6支持需要18个字节(VARBINARY(16))。同时,NVARCHAR需要30个字节用于IPv4,78个字节用于IPv6 ...(在网上搜索inet_ntoa,inet_aton,inet_ntop,inet_pton以了解如何在地址的二进制和字符串表示之间切换)
  • 而不是在两个单独的表中存储类似的数据,添加一个BIT类型的Restorable标志列,指示是否可以恢复日志条目
  • 您对Info列的想法是正确的:使用TEXT或NTEXT数据类型会更好
  • 而不是为Action使用NVARCHAR类型,您可以考虑使用包含所有可能操作的Action表(假设它们是有限数字),并使用整数外键引用它们( int越小越好)

索引优化也非常重要。如果查询同时测试多个列,请在多个列上使用索引。例如,如果在特定时间范围内选择与特定IP相对应的所有可恢复行,这将大大提高查询的速度:

CREATE NONCLUSTERED INDEX IX_IndexName ON log (Restorable ASC, IP ASC, LogDate ASC)

如果您需要从特定操作对应的IP地址检索所有可恢复的行,则在给定的时间范围内,应该选择索引:

CREATE NONCLUSTERED INDEX IX_IndexName ON log (IP ASC, Action ASC, LogDate ASC)

说实话,我实际上需要查看完整的SQL查询才能进行适当的优化...

答案 1 :(得分:3)

表格增强功能的选项:

  1. 添加Restorable bit null列并在其上创建过滤索引。

  2. 'XML'数据类型是LOB数据类型,存储在行外。如果您没有使用任何XML data type methods,那么您不需要它。它确实妨碍了你的表现。添加XML_code varchar () null列并复制XML列中的所有数据。

  3. 选择列的长度,以使最大行大小(所有列的总最大大小)保持小于8Kb。如果行适合8kb,则Varchar (MAX)列可以存储在行中。因此,如果您有大量简短的XML,那么VARCHAR (MAX)可以提供帮助。

    1. 如果您不使用Unicode数据,请将所有NVARCHAR更改为VARCHAR

    2. 使用带有UNION ALL线索的Where来过滤重复项而非UNION

    3. UNIQUEIDENTIFIER列对此没有帮助。如果两个记录不能以合理的方式具有相同的datetime(或datetime2) value, then it can you unique ID on its own. Alternatively consider changint ID column to int as you order by int`。

    4. 重新思考:数字(4)无济于事。在两个表上创建索引,这些索引遵循Where子句和JOIN列。

      进行多次迭代:简化数据类型 - 检查性能。创建索引 - 再次检查。等等。在最小化使用空间和可用性之间应该保持平衡。您可能希望将一些数据保留在文本中,而不是编码为int或binary。

      使用Profiler或Tuning顾问来确定瓶颈和改进机会。

答案 2 :(得分:1)

我将疯狂猜测标识某些内容是否“可恢复”的属性是Action列。如果是这种情况,则按该列对表进行分区,并忘记log_restore表。

MSDN - Partitioned Table and Index Concepts

答案 3 :(得分:1)

首先要担心的是机器的内存,服务器有多少?那么你应该与你的数据库大小进行比较,或者只是你正在处理的表的大小。如果内存与表的大小相比较低,则必须向服务器添加更多内存。这是你做的第一件事。

A Sysadmin’s Guide to Microsoft SQL Server Memory