【问题标题】:30 mil records into 700 mil lookup, best practices - SQL Server 083000 万条记录到 7 亿条查找中,最佳实践 - SQL Server 08
【发布时间】:2013-08-01 13:20:07
【问题描述】:

我有一个 SQL 脚本,它针对各种条件查看 30-40 个“代码”,并从大约 3000 万行的大型 2 表(在 PK 上加入)源中找到匹配的记录。脚本完成后,我最终得到了一个近 8 亿多万的查找表。记录(2500 万 * ~35 个代码)。

每个代码都有自己的选择语句。他们中的大多数人都在寻找相同的来源,只是使用了不同的条件。一些代码的查询加入了一个额外的源表来获取lookup_value。

例如:

INSERT INTO LookupTable 
SELECT 01 AS code, t1.lookup_value, t1.PK, t2.PK
FROM Table1 t1
JOIN Table2 t2 ON t1.FK = t2.PK
WHERE <code 1 condition> = true

INSERT INTO LookupTable     
SELECT 02 AS code, t1.lookup_value, t1.PK, t2.PK
FROM Table1 t1
JOIN Table2 t2 ON t1.FK = t2.PK
WHERE <code 2 condition> = true

INSERT INTO LookupTable     
SELECT 03 AS code, CASE WHEN t1.lookup_value IN 'A1','B1','C1' THEN 1 ELSE 0 END, t1.PK, t2.PK
FROM Table1 t1
JOIN Table2 t2 ON t1.FK = t2.PK
WHERE <code 3 condition> = true

INSERT INTO LookupTable     
SELECT 04 AS code, CASE WHEN t3.lookup_value IN 'A1','B1','C1' THEN 1 ELSE 0 END, t1.PK, t2.PK
FROM Table1 t1
JOIN Table2 t2 ON t1.FK = t2.PK
JOIN Table3 t3 ON t1.FK = t3.PK
WHERE <code 4 condition> = true

 --  ... <continues 30 more times>

(部分代码还有多查询语句、临时表等,但如果我能处理好上面的,我可以自己解决。)

就目前而言,脚本需要大约 6 个小时才能在功能强大的服务器上运行。这是一个预先存在的系统,我没有重新设计它的工作方式的选项;需要巨大的查找表。

我忍不住想,扫描同样的 30 00 万。行,30 多次是一种低效的方法!对于更好的性能,或者至少是更易于管理的代码有什么想法吗?

我一直在考虑创建 .Net CLR TVF 或索引视图,但我对新想法持开放态度!

【问题讨论】:

    标签: sql-server performance sql-server-2008 loops insert


    【解决方案1】:

    编辑更新答案

    使用common table expression 将您的 3000 万条记录表预解析为一个临时结果集,然后从中进行几次插入选择...

    WITH Table_CTE (code, lookup_value, pk1, pk2)
    AS
    -- Define the CTE query.
    (
        SELECT
            CASE WHEN <code 1 condition> THEN 01
            CASE WHEN <code 2 condition> THEN 02
            CASE WHEN <code 3 condition> THEN 03
            CASE WHEN <code 4 condition> THEN 04
            ...
        END code, t1.lookup_value, t1.PK as pk1, t2.PK as pk2
        FROM Table1 t1
        JOIN Table2 t2 ON t1.FK = t2.PK
        JOIN Table3 t3 ON t1.FK = t3.PK
    )
    
    INSERT INTO LookupTable
    SELECT code, lookup_value, pk1, pk2
    FROM Table_CTE
    WHERE code = '01'
    
    INSERT INTO LookupTable
    SELECT code, lookup_value, pk1, pk2
    FROM Table_CTE
    WHERE code = '02'
    
    INSERT INTO LookupTable
    SELECT code, lookup_value, pk1, pk2
    FROM Table_CTE
    WHERE code = '03'
    

    【讨论】:

    • 这只会给我一个代码的匹配项,所以 30 百万。当我需要 30 百万时行。每个代码。
    【解决方案2】:

    我假设任何条件只能满足一次。

    那么它是一个简单的(小心,未经测试!):

    INSERT INTO LookupTable 
    SELECT
      code = c.val
      t1.lookup_value, 
      t1.PK, 
      t2.PK
    FROM 
      Table1 t1
      JOIN Table2 t2 
        ON t1.FK = t2.PK
      CROSS APPLY (
        SELECT val = CASE 
          WHEN <code 1 condition> THEN 01
          WHEN <code 2 condition> THEN 02
          ...
          WHEN <code 34 condition> THEN 34 
          ELSE 00 END
      ) v
    WHERE c.val != 99
    

    如果我的假设 != true,那么我相信您(或某人)应该重新考虑设计。

    【讨论】:

    • 这行得通 - 我必须为我的代码包含一个表,因此 FROM Table1 JOIN table2 变成 FROM (SELECT * FROM tblCodes, Table1 JOIN Table2),并且我按预期得到每个代码 20+ mil .不过仍然需要看看是否有性能提升。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-11
    • 2010-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多