sql - 大表 UNION 的性能问题

标签 sql sql-server database batch-processing

我有七个大表,可以随时存储 100 到 100 万行。我将它们命名为 LargeTable1LargeTable2LargeTable3LargeTable4...LargeTable7。这些表大多是静态的:没有更新,也没有新的插入。它们仅每两周或每月更改一次,此时它们会被截断,并在每个寄存器中插入一批新的寄存器。

所有这些表都有三个共同字段:HeadquartersCountryFileHeadquartersCountry 是格式为“000”的数字,但在其中两个表中,由于某些其他系统需求,它们被解析为 int

我有另一个较小的表,名为Headquarters,其中包含每个总部的信息。该表的条目很少。实际上最多 1000 个。

现在,我需要创建一个存储过程,返回所有出现在大型表中但在 Headquarters 表中不存在或已被删除的总部(该表在逻辑上被删除:它有一个 DeletionDate 字段来检查这一点)。

这是我尝试过的查询:

CREATE PROCEDURE deletedHeadquarters
AS
BEGIN
    DECLARE @headquartersFiles TABLE
    (
        hq int,
        countryFile varchar(MAX)
    );

    SET NOCOUNT ON

    INSERT INTO @headquartersFiles
    SELECT headquarter, CONCAT(country, ' (', file, ')')
    FROM
    (
        SELECT DISTINCT CONVERT(int, headquarter) as headquarter,
                        CONVERT(int, country) as country,
                        file
        FROM            LargeTable1     
        UNION
        SELECT DISTINCT headquarter,
                        country,
                        file
        FROM            LargeTable2
        UNION
        SELECT DISTINCT headquarter,
                        country,
                        file
        FROM            LargeTable3
        UNION
        SELECT DISTINCT headquarter,
                        country,
                        file
        FROM            LargeTable4
        UNION
        SELECT DISTINCT headquarter,
                        country,
                        file
        FROM            LargeTable5
        UNION
        SELECT DISTINCT headquarter,
                        country,
                        file
        FROM            LargeTable6
        UNION
        SELECT DISTINCT headquarter,
                        country,
                        file
        FROM            LargeTable7
    ) TC

    SELECT  RIGHT('000' + CAST(st.headquarter AS VARCHAR(3)), 3) as headquarter,
            MAX(s.deletionDate) as deletionDate,
            STUFF
            (
                (SELECT DISTINCT ', ' + st2.countryFile
                FROM @headquartersFiles st2
                WHERE st2.headquarter = st.headquarter
                FOR XML PATH('')),
                1,
                1,
                ''
            ) countryFile
    FROM    @headquartersFiles as st
    LEFT JOIN headquarters s ON CONVERT(int, s.headquarter) = st.headquarter
    WHERE   s.headquarter IS NULL
       OR   s.deletionDate IS NOT NULL
    GROUP BY st.headquarter

END

这个 sp 的性能对于我们的应用程序来说不够好。目前需要大约 50 秒才能完成,每个表的总行数如下(只是为了让您了解大小):

  • LargeTable1:1516666 行
  • LargeTable2:645740 行
  • LargeTable3:1950121 行
  • LargeTable4:779336 行
  • LargeTable5:1100999 行
  • LargeTable6:16499 行
  • LargeTable7:24454 行

我可以做些什么来提高性能?我尝试执行以下操作,但没有太大区别:

  • 批量插入本地表,排除已经插入的总部,然后更新countryFile字段,重复的
  • 为该 UNION 查询创建 View
  • 为总部字段的 LargeTables 创建索引

我还考虑过在 LargeTables 更改后将这些缺失的总部插入永久表中,但是 Headquarters 表可以更频繁地更改,我不希望这样做必须更改其模块以保持这些东西整洁和更新。但如果这是最好的选择,我会选择它。

谢谢

最佳答案

使用这个过滤器

LEFT JOIN headquarters s ON CONVERT(int, s.headquarter) = st.headquarter
WHERE   s.headquarter IS NULL
   OR   s.deletionDate IS NOT NULL

并将其添加到联合中的每个单独查询中并插入到@headquartersFiles

这看起来可能会产生更多的过滤器,但实际上会加快速度,因为您在开始作为联合进行处理之前就进行了过滤。

同时取出所有 DISTINCT,它可能不会加快速度,但这看起来很愚蠢,因为您正在执行 UNION 而不是全部 UNION。

关于sql - 大表 UNION 的性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38150933/

相关文章:

sql-server - SQL Server - Excel 的 CHOOSE 函数的任何等效项吗?

sql - 如何获得分组列的前 10 名?

mysql - 数据库恢复

mysql - 如何更改表的默认排序规则?

mysql - 如果 currentdatetime > datetime+5 则触发删除行

sql-server - 如何在一个SQL查询中连接来自两个不同SQL Server实例的表

mysql - 如何三重连接表以查找和查找匹配两个事物的条目?

mysql - 如何提高大表中的插入时间?

mysql - 在mysql中使用内连接语法更新表

javascript - 获取 SQL 表值的最有效方法是什么?