加速在非常大的sql表中查找记录

时间:2014-02-20 10:30:50

标签: sql sql-server entity-framework

抱歉我的英语不好。

请假设我们要保存所有日期和每天的所有商业行为(卖出和购买)

100或更多动作。 3年后,我们有一张超过10万行的桌子。现在我们想得到一个

2年前5月20日至5月25日期间所做的行动报告。

SELECT * 
  FROM actions 
 WHERE Date BETWEEN 2012/5/20 AND 2012/5/25

问题是必须读取所有100,000行才能执行此操作。

首先,我决定将每个月的数据分开。但我不知道如何

使用实体框架处理此问题。请问有什么建议吗?感谢。

3 个答案:

答案 0 :(得分:3)

  

问题是必须读取所有100,000行才能执行此操作。

答:即使 - 除非你在旧手机上运行,​​否则这将是微不足道的。我经常从100亿行表中汇总1亿行。

B:了解索引是什么,然后不必读取所有行。

答案 1 :(得分:2)

当表中有X行数时,不要认为查询会表现不好。你应该测试一下!

为每个表创建几百万行测试数据非常容易(应该在开发或测试环境中完成)。然后,您可以测试每个查询,并确切了解它们的“慢”程度。

此代码段将创建一个表并向其插入1 000 000行。试一试,然后尝试在其上运行一些不同的查询。

CREATE TABLE [dbo].[Orders](
    [OrderId] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
    [CustomerId] [int] NOT NULL,
    [ArticleId] [int] NOT NULL,
    [TotalAmount] [decimal](19, 6) NULL,
    [OrderDate] DATETIME NOT NULL DEFAULT(GETDATE())
);

WITH
            C0(c) AS (SELECT 1 UNION ALL SELECT 1),
            C1(c) AS (SELECT 1 FROM C0 AS A CROSS JOIN C0 AS B),
            C2(c) AS (SELECT 1 FROM C1 AS A CROSS JOIN C1 AS B),
            C3(c) AS (SELECT 1 FROM C2 AS A CROSS JOIN C2 AS B),
            C4(c) AS (SELECT 1 FROM C3 AS A CROSS JOIN C3 AS B),
            C5(c) AS (SELECT 1 FROM C4 AS A CROSS JOIN C4 AS B),
            C6(c) AS (SELECT 1 FROM C5 AS A CROSS JOIN C5 AS B),

        numbers(n) AS(
                        SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
                FROM C6)

INSERT dbo.Orders
        ( CustomerId ,
          ArticleId ,
          TotalAmount,
          OrderDate
        ) 
SELECT TOP 1000000
        N % 150 + 1, 
        N % 100 + 1, 
        N % 500 + 20,
        DATEADD(MINUTE, (N - 1), '2014-01-01')
FROM numbers;

该表格将包含1 000 000个订单,由150个不同的客户完成,共100个不同的文章,每个订单的金额在20到520之间。从2014-01-01 00:00:00开始,每个订单在彼此之间放置一分钟。

使用该数据,以下查询仍在我的工作站上一秒钟内执行:

SELECT * FROM dbo.Orders WHERE orderDate BETWEEN '2014-05-01' AND '2014-08-01' 

数据在磁盘上的倾向比您想象的要小得多。这个包含一百万行的表仍然只占用大约70MB的空间。

EXEC sys.sp_spaceused @objname = N'Orders'
--name      rows        reserved    data        index_size  unused
--Orders    1000000     70432 KB    37560 KB    32072 KB    800 KB

从磁盘读取这么多MB需要多长时间? 2-3秒,桌面上最糟糕的情况。

添加索引 评论其他答案。

我在日期列上添加了一个索引,但查询优化器仍然认为扫描整个表更好。这可能是因为在日期范围内对所有这些订单执行查找比从磁盘顺序读取所有订单更昂贵。根据表中的数据,可能会也可能不会使用这些索引。这就是为什么你应该生成与预期负载相匹配的测试数据,然后才能调整查询并创建“正确”的索引。

对于这个特定的表,可能是问题中的那个,我建议将CLUSTERED索引放在日期列而不是主键上。

答案 2 :(得分:1)

首先,对于SQL Server来说,只有100.000行不会出现问题,只要你拥有正确的索引,即使在30年后它也能正常运行。

如果您仍想分割它,我不会手动执行,这将太乱,只需使用表分区,由sql server本身处理(http://technet.microsoft.com/en-us/library/ms190787.aspx获取更多信息)