我有一个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。我显然拥有进行此类查询所需的计算机能力,但查询仍然需要很长时间。
答案 0 :(得分:6)
你可能错过了phonenumber专栏的索引。
CREATE INDEX IX_PHONERECORDS_PHONENUMBER_FIRSTNAME
ON dbo.PhoneRecords (PhoneNumber) INCLUDE (FirstName)
如果这没有帮助,请发布execution plan(CTRL+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)。