SQL查询 - 20mil记录 - 返回信息的最佳实践

时间:2010-04-02 09:01:51

标签: sql-server

我有一个SQL数据库,其中包含以下表格:

Table: PhoneRecords
--------------
ID(identity Seed)
FirstName
LastName
PhoneNumber
ZipCode

非常简单的直接表。该表有超过2000万条记录。我正在寻找最好的方法来执行查询,根据表中的区域代码提取记录。例如,这是我已经完成的示例查询。

SELECT phonenumber, firstname
FROM [PhoneRecords]
WHERE (phone LIKE '2012042%') OR
      (phone LIKE '2012046%') OR
      (phone LIKE '2012047%') OR
      (phone LIKE '2012083%') OR
      (phone LIKE '2012088%') OR
      (phone LIKE '2012841%')

正如您所看到的,这是一个丑陋的查询,但它可以完成工作(如果我没有遇到超时问题)

有人能告诉我速度/优化的最佳方法来执行上述查询以显示结果吗?目前,上述查询大约需要2个小时才能完成9gb 1600mhz ram,i7 930 quadcore OC'd 4.01ghz。我显然拥有进行此类查询所需的计算机能力,但查询仍然需要很长时间。

8 个答案:

答案 0 :(得分:6)

你可能错过了phonenumber专栏的索引。

CREATE INDEX IX_PHONERECORDS_PHONENUMBER_FIRSTNAME 
  ON dbo.PhoneRecords (PhoneNumber) INCLUDE (FirstName)

如果这没有帮助,请发布execution planCTRL+M)。

答案 1 :(得分:5)

首先,您需要列phone上的索引。如果您没有,请添加它。

如果它仍然运行缓慢,您可能会尝试使用UNION ALL而不是OR,因为优化程序可以更轻松地使用它。这是有效的,因为您构建条件的方式可以保证结果不同。因此,您的查询可以重写为:

SELECT phonenumber, firstname FROM [PhoneRecords] WHERE phone LIKE '2012042%'
UNION ALL
SELECT phonenumber, firstname FROM [PhoneRecords] WHERE phone LIKE '2012046%'
UNION ALL
SELECT phonenumber, firstname FROM [PhoneRecords] WHERE phone LIKE '2012047%'
UNION ALL
SELECT phonenumber, firstname FROM [PhoneRecords] WHERE phone LIKE '2012083%'
UNION ALL
SELECT phonenumber, firstname FROM [PhoneRecords] WHERE phone LIKE '2012088%'
UNION ALL
SELECT phonenumber, firstname FROM [PhoneRecords] WHERE phone LIKE '2012041%'

此查询应该能够使用索引有效运行。

您应该在运行实际查询之前查看执行计划,并确保没有TABLE SCAN或INDEX SCAN。

答案 2 :(得分:2)

你有索引吗?第一步是在PhoneNumber列上放置索引。如果这还不够(我不知道在索引列中搜索部分字符串的确切细节)我建议添加另一个名为“AreaCode”的列,它可以从PhoneNumber列自动计算。然后,您可以在AreaCode列上添加索引。

答案 3 :(得分:2)

第一个也是非常明显的问题是你有索引吗?如果要对其进行查询,则需要至少在电话号码上创建索引。您应该创建一个覆盖索引,其中包含您想要的字段和where子句中的字段,这样计算机就不必浪费时间在索引中找到该行后获取所需的信息。显然,另一方面,你的索引越大,你的查询就越慢。

答案 4 :(得分:2)

您可以拆分电话号码栏:[区号],[电话号码]

然后,如果此查询是此表的应用程序中“最重要”,并且返回的行数/总行数很高,则在[区号]上添加CLUSTERED索引,否则添加标准索引。

您也可以按原样保留“电话号码”列,并将其直接编入索引,具体取决于您的应用。

答案 5 :(得分:1)

首先,我将电话栏拆分为“区号”和“电话号码”。

另外,我会把这个数字转换为int;索引的执行速度会更快。

AreaCode = 2012042

应该比

快得多
PhoneNumber LIKE '2012042%'

答案 6 :(得分:1)

即使您正在进行表扫描(即使您有索引也会发生,如果选择性很低),您的查询执行速度应该超过2小时。如果没有与其他查询扫描的其他表竞争,并且sqlserver最大内存足够大,那么您的表小到足以完全适合sql server缓冲池。因此,虽然您可以执行一些技巧,例如添加索引或在区域+电话中拆分电话号码,但您应该调查sql server配置以及系统配置。

答案 7 :(得分:0)

http://igoro.com/archive/precomputed-view-a-cool-and-useful-sql-pattern

创建一个物化视图,其中包含前n列电话号码作为自己的列。然后,您可以查询区号列并包含名称。预先计算区号,这样就不必在每次选择时都进行。如果可以帮助,请不要使用或运算符。使用union来帮助查询计划使用索引。

实际上,您正在运行的查询将执行20,000,000次x次比较,其中x是您每次执行选择时要搜索的区号的数量。通过查询精确的索引列,您根本不需要转到表,我认为可以以有效的方式搜索索引O(log n)。