您在SQL Server上优化大表(+ 1M行)的方法是什么?

时间:2008-12-03 16:25:11

标签: sql-server optimization bigtable

我正在将巴西股票市场数据导入SQL Server数据库。现在我有一张表格,其中包含三种资产的价格信息:股票,期权和远期合约。我仍然在2006年的数据,该表有超过50万的记录。我有更多12年的数据需要导入,因此该表肯定会超过一百万条记录。

现在,我的第一个优化方法是将数据保持在最小值,因此我将行大小减少到平均60字节,并使用以下列:

[Stock] [int] NOT NULL
[Date] [smalldatetime] NOT NULL
[Open] [smallmoney] NOT NULL
[High] [smallmoney] NOT NULL
[Low] [smallmoney] NOT NULL
[Close] [smallmoney] NOT NULL
[Trades] [int] NOT NULL
[Quantity] [bigint] NOT NULL
[Volume] [money] NOT NULL

现在,第二种优化方法是制作聚簇索引。实际上主要索引是自动clusted的,我用Stock和Date字段作为复合索引。这是独一无二的,我不能在同一天为同一股票提供两个报价数据。

clusted index确保同一股票的报价保持在一起,可能按日期排序。这第二个信息是真的吗?

目前有50万条记录,它需要 200ms 才能从特定资产中选择 700 报价。我相信随着桌子的增长,这个数字会越来越高。

现在我采用第三种方法,可能会将表格分成三个表格,每个表格针对特定市场(股票,期权和远期)。这可能会将表格大小减少1/3。现在,这种方法有用还是无关紧要?现在,这个表有50mb的大小,所以它可以完全适合RAM而不会有太多麻烦。

另一种方法是使用SQL Server的分区功能。我不太了解它,但我认为它通常在表很大时使用,你可以跨越多个磁盘来减少I / O延迟,我是对的吗?在这种情况下,分区是否有用?我相信我可以在不同的表中划分最新的值(最近几年)和最旧的值,寻找最新数据的概率更高,并且通过小分区它可能会更快,对吧?

有什么其他好方法可以尽可能快地实现这一目标?该表的主要选择用途是用于从特定资产中寻找特定范围的记录,例如最近3个月的资产X.将会有另一种用法,但这将是最常见的,可能超过3k执行用户同时。

9 个答案:

答案 0 :(得分:11)

  1. 在100万条记录中,我不认为这是一个特别大的表需要不寻常的优化技术,例如拆分表,非正规化等等。但是当你尝试了所有正常的方法时,这些决定就会出现。这会影响您使用标准查询技术的能力。
  2.   

    现在,第二种优化方法是制作聚簇索引。实际上主要索引是自动clusted的,我用Stock和Date字段作为复合索引。这是独一无二的,我不能在同一天为同一股票提供两个报价数据。

         

    clusted index确保来自同一股票的报价保持在一起,并且可能按日期排序。这第二个信息是真的吗?

    这在逻辑上是正确的 - 聚集索引定义了磁盘上记录的逻辑顺序,这是您应该关注的全部内容。 SQL Server可能会放弃在物理块内进行排序的开销,但它仍然会像它一样表现,因此它并不重要。在任何情况下,查询一个库存可能是1或2页读取;并且优化器不会从页面读取中的无序数据中获益。

      

    目前拥有50万条记录,从特定资产中选择700条报价大约需要200毫秒。我相信随着桌子的增长,这个数字会越来越高。

    不一定显着。表大小和查询速度之间没有线性关系。通常有更多的考虑更重要。我不会在你描述的范围内担心它。这是你担心的原因吗? 200毫秒在我看来是伟大的,足以让你到达你的桌子加载的地步,你可以开始做真实的测试,并更好地了解现实生活中的表现。

      

    现在我采用第三种方法,可能会将表格分成三个表格,每个表格针对特定市场(股票,期权和远期)。这可能会将表格大小减少1/3。现在,这种方法有用还是无关紧要?现在,这个表有50mb的大小,所以它可以完全适合RAM而不会有太多麻烦。

    没有!这种优化是不成熟的,它可能是死的。

      

    另一种方法是使用SQL Server的分区功能。

    同样的评论。您将能够坚持很长时间,进行严格的逻辑,完全规范化的架构设计。

      

    有什么其他好方法可以尽可能快地实现这一目标?

    最好的第一步是群集库存。在您查看每秒插入的多个记录之前,插入速度根本没有任何影响 - 我在这里看不到任何附近任何活动。这应该让你接近最大效率,因为它将有效地读取与股票相关的每个记录,这似乎是你最常见的指数。任何进一步的优化都需要基于测试来完成。

答案 1 :(得分:10)

百万条记录真的不是那么大。这听起来好像搜索的时间太长了 - 您要搜索的列是否已编入索引?

与以往一样,第一个调用端口应该是SQL分析器和查询计划评估程序。询问SQL Server它会对您感兴趣的查询做些什么。我相信您甚至可以要求它建议更改,例如额外的索引。

我还没有开始进入分区等 - 正如你所说的那样,它现在应该全部放在内存中,所以我怀疑你的问题更可能是一个缺失的索引。

答案 2 :(得分:3)

首先检查该查询的执行计划。确保您的索引正在使用中。我发现了。一百万条记录不是很多。为了给出一些观点,我们有一个库存表,其中包含3000万行,我们的整个查询加入了大量的表,并且可以在200 MS以下运行大量计算。我们发现在四进制64位服务器上,我们可以有更多的记录,所以我们从不打扰分区。

您可以使用SQL Profier查看执行计划,或者只运行SQL Management Studio或查询分析器中的查询。

答案 3 :(得分:3)

重新评估索引......这是最重要的部分,数据的大小并不重要,但它确实存在,但并不完全是出于速度目的。

我的建议是重新构建该表的索引,为最需要的列创建一个复合索引。现在您只有少量记录可以使用不同的索引,否则一旦您拥有表中的所有历史数据,尝试新事物会非常烦人。

在您查看查询后,将查询计划评估程序作为您的朋友,并检查引擎是否使用正确的索引。

我刚读了你的最后一篇文章,有一件事是我没有得到的,你在插入数据时查询表格?同时?。做什么的?通过插入,你的意思是一个记录或数十万?你是怎么插入的?一个接一个?

但同样关键的是索引,不要搞乱分区和东西......特别是有一个millon记录,没什么,我有150个记录的表,并返回40k特定记录需要引擎1500毫秒......

答案 4 :(得分:1)

我在学区工作,我们必须跟踪每个学生的出勤情况。这就是我们赚钱的方式。我的每个学生每日出勤率的表格目前为3890万。我可以很快从一个学生的出勤率中提取出来。我们在这个表上保留了4个索引(包括主键)。我们的聚集索引是学生/日期,它保留了所有学生的记录。在插入学生的旧记录的情况下,我们对此表中的插入有所了解,但对我们来说这是一个值得冒险的风险。

关于选择速度,我肯定会在你的环境中利用缓存。

答案 5 :(得分:1)

您已经提到主键是(Stock,Date)和群集上的复合词。这意味着该表按Stock排列,然后按Date排序。无论何时插入新行,都必须将其插入到表的中间,这会导致其他行被推出到其他页面(页面拆分)。

我建议尝试将主键反转为(日期,库存),并在库存中添加非聚集索引以便于快速查找特定库存。这将允许插入始终发生在表的末尾(假设您按日期顺序插入),并且不会影响表的其余部分,并且页面拆分的可能性较小。

答案 6 :(得分:0)

执行计划显示它使用聚簇索引非常好,但我忘了一个非常重要的事实,我还在插入数据!插件可能经常锁定表格。我们有办法看到这个瓶颈吗?

执行计划似乎没有显示任何有关锁定问题的信息。

现在这个数据只是历史数据,当导入过程完成后,插入将停止并且不常用。但是我很快会有一个更大的实时数据表,这将受到这个常量插入问题的影响,并且会比这个表更大。因此,非常欢迎任何优化此类情况的方法。

答案 7 :(得分:0)

另一个解决方案是为每年创建一个历史表,并将所有这些表放在一个历史数据库中,填写所有这些表,然后为它们创建适当的索引。完成此操作后,您将无需再次触摸它们。你为什么要继续插入数据?要查询所有这些表,您只需“联合所有”:p

当前年度表应该与此历史表非常不同。根据我的理解,你打算在旅途中插入记录?,我计划一些不同的东西,比如每天不时地进行批量插入或类似的东西。当然,这一切都取决于你想做什么。

这里的问题似乎出现在设计中。我会去寻找新的设计。你现在拥有的那个我理解它不合适的。

答案 8 :(得分:0)

  

实际上主要索引是自动clusted的,我用Stock和Date字段作为复合索引。这是独一无二的,我不能在同一天为同一股票提供两个报价数据。

     

clusted index确保来自同一股票的报价保持在一起,并且可能按日期排序。这第二个信息是真的吗?

SQL Server中的索引始终按索引中的列顺序排序。因此,[股票,日期]的指数将首先对股票进行排序,然后对股票进行排序。 [日期,股票]的指数将首先按日期排序,然后在股票日期内进行排序。

进行查询时,应始终在WHERE部分中包含索引的第一列,否则无法有效使用索引。

针对您的具体问题:如果库存的日期范围查询是最常见的用法,那么请在[date,stock]上执行主键,这样数据将按日期顺序存储在磁盘上,您应该获得最快的访问权限。根据需要构建其他索引。插入大量新数据后,索引重建/统计更新。