2

我正在移植一个创建CROSS JOIN两个表的 MASSIVE 的进程。结果表包含 15m 条记录(看起来该过程与 2600 行表和 12000 行表进行 30m 交叉连接,然后进行一些必须将其分成两半的分组)。行相对较窄 - 只有 6 列。它已经运行了5个小时,没有完成的迹象。我只是注意到已知商品和我对交叉连接的期望之间的计数差异,所以我的输出没有分组或重复数据删除,这将使决赛桌减半 - 但这似乎仍然不会完成任何时间很快。

首先,如果可能的话,我将寻求从流程中消除该表 - 显然它可以通过单独加入两个表来替换,但现在我无法看到它使用的其他任何地方。

但是鉴于现有的流程可以做到(在更短的时间内,在功能不太强大的机器上,使用 FOCUS 语言),是否有任何选项可以提高CROSS JOINSQL Server(2005)中大 s 的性能(硬件不是真正的选项,这个盒子是 64 位 8 路 32 GB RAM)?

细节:

它是在 FOCUS 中以这种方式编写的(我试图产生相同的输出,它是 SQL 中的 CROSS JOIN):

JOIN CLEAR *
DEFINE FILE COSTCENT
  WBLANK/A1 = ' ';
  END
TABLE FILE COSTCENT
  BY WBLANK BY CC_COSTCENT
  ON TABLE HOLD AS TEMPCC FORMAT FOCUS
  END

DEFINE FILE JOINGLAC
  WBLANK/A1 = ' ';
  END
TABLE FILE JOINGLAC
  BY WBLANK BY ACCOUNT_NO BY LI_LNTM
  ON TABLE HOLD AS TEMPAC FORMAT FOCUS INDEX WBLANK

JOIN CLEAR *
JOIN WBLANK IN TEMPCC TO ALL WBLANK IN TEMPAC
DEFINE FILE TEMPCC
  CA_JCCAC/A16=EDIT(CC_COSTCENT)|EDIT(ACCOUNT_NO);
  END
TABLE FILE TEMPCC
  BY CA_JCCAC BY CC_COSTCENT AS COST CENTER BY ACCOUNT_NO
  BY LI_LNTM
  ON TABLE HOLD AS TEMPCCAC
  END

所以所需的输出实际上是一个 CROSS JOIN (它从每一侧加入一个空白列)。

在 SQL 中:

CREATE TABLE [COSTCENT](
       [COST_CTR_NUM] [int] NOT NULL,
       [CC_CNM] [varchar](40) NULL,
       [CC_DEPT] [varchar](7) NULL,
       [CC_ALSRC] [varchar](6) NULL,
       [CC_HIER_CODE] [varchar](20) NULL,
 CONSTRAINT [PK_LOOKUP_GL_COST_CTR] PRIMARY KEY NONCLUSTERED
(
       [ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY
= OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

CREATE TABLE [JOINGLAC](
       [ACCOUNT_NO] [int] NULL,
       [LI_LNTM] [int] NULL,
       [PR_PRODUCT] [varchar](5) NULL,
       [PR_GROUP] [varchar](1) NULL,
       [AC_NAME_LONG] [varchar](40) NULL,
       [LI_NM_LONG] [varchar](30) NULL,
       [LI_INC] [int] NULL,
       [LI_MULT] [int] NULL,
       [LI_ANLZ] [int] NULL,
       [LI_TYPE] [varchar](2) NULL,
       [PR_SORT] [varchar](2) NULL,
       [PR_NM] [varchar](26) NULL,
       [PZ_SORT] [varchar](2) NULL,
       [PZNAME] [varchar](26) NULL,
       [WANLZ] [varchar](3) NULL,
       [OPMLNTM] [int] NULL,
       [PS_GROUP] [varchar](5) NULL,
       [PS_SORT] [varchar](2) NULL,
       [PS_NAME] [varchar](26) NULL,
       [PT_GROUP] [varchar](5) NULL,
       [PT_SORT] [varchar](2) NULL,
       [PT_NAME] [varchar](26) NULL
) ON [PRIMARY]

CREATE TABLE [JOINCCAC](
       [CA_JCCAC] [varchar](16) NOT NULL,
       [CA_COSTCENT] [int] NOT NULL,
       [CA_GLACCOUNT] [int] NOT NULL,
       [CA_LNTM] [int] NOT NULL,
       [CA_UNIT] [varchar](6) NOT NULL,
 CONSTRAINT [PK_JOINCCAC_KNOWN_GOOD] PRIMARY KEY CLUSTERED
(
       [CA_JCCAC] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY
= OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

使用 SQL 代码:

INSERT  INTO [JOINCCAC]
       (
        [CA_JCCAC]
       ,[CA_COSTCENT]
       ,[CA_GLACCOUNT]
       ,[CA_LNTM]
       ,[CA_UNIT]
       )
       SELECT  Util.PADLEFT(CONVERT(varchar, CC.COST_CTR_NUM), '0',
                                     7)
               + Util.PADLEFT(CONVERT(varchar, GL.ACCOUNT_NO), '0',
                                       9) AS CC_JCCAC
              ,CC.COST_CTR_NUM AS CA_COSTCENT
              ,GL.ACCOUNT_NO % 900000000 AS CA_GLACCOUNT
              ,GL.LI_LNTM AS CA_LNTM
              ,udf_BUPDEF(GL.ACCOUNT_NO, CC.COST_CTR_NUM, GL.LI_LNTM, 'N') AS CA_UNIT
       FROM   JOINGLAC AS GL
       CROSS JOIN COSTCENT AS CC

根据随后如何使用此表,它应该能够从流程中消除,只需加入用于构建它的两个原始表即可。但是,这是一个非常大的移植工作,我可能有一段时间找不到表的用法,所以我想知道是否有任何技巧可以CROSS JOIN及时 ing 像这样的大表(特别是考虑到现有的流程in FOCUS 能够更快地做到这一点)。这样我就可以验证我构建替换查询的正确性,然后用视图或其他方式将其分解。

我还在考虑将 UDF 和字符串操作分解并首先执行 CROSS JOIN 以稍微分解该过程。

到目前为止的结果:

事实证明,UDF 确实对性能有很大贡献(负面)。但是 15m 行交叉连接和 30m 行交叉连接之间似乎也存在很大差异。我没有 SHOWPLAN 权限(嘘),所以我无法判断它使用的计划在更改索引后是更好还是更差。我还没有重构它,但我希望整个表很快就会消失。

4

3 回答 3

2

检查该查询显示仅使用了一个表中的一列,并且仅使用了另一表中的两列。由于使用的列数非常少,因此可以通过覆盖索引轻松增强此查询:

CREATE INDEX COSTCENTCoverCross ON COSTCENT(COST_CTR_NUM)
CREATE INDEX JOINGLACCoverCross ON JOINGLAC(ACCOUNT_NO, LI_LNTM)

以下是我进一步优化的问题:

当您将查询放入查询分析器并点击“显示估计的执行计划”按钮时,它将显示它将要做什么的图形表示。

连接类型:那里应该有一个嵌套循环连接。(其他选项是合并连接和哈希连接)。如果您看到嵌套循环,则可以。如果您看到合并连接或哈希连接,请告诉我们。

表格访问顺序:一直到顶部并一直滚动到右侧。第一步应该是访问一个表。那是哪个表,使用什么方法(索引扫描,聚集索引扫描)?使用什么方法访问另一个表?

并行性:您应该在计划中的几乎所有图标上看到锯齿状的小箭头,表明正在使用并行性。如果你看不到这一点,那就是一个大问题!

udf_BUPDEF 与我有关。它是否从其他表中读取?Util.PADLEFT 不太关心我,但仍然.. 它是什么?如果它不是数据库对象,请考虑改用它:

RIGHT('z00000000000000000000000000' + columnName, 7)

JOINCCAC 上是否有任何触发器?索引呢?使用这么大的插入,您将希望删除该表上的所有触发器和索引。

于 2008-12-10T05:41:09.967 回答
2

继续其他人的说法,包含在 select 中使用的查询的 DB 函数总是使我的查询非常慢。在我的脑海中,我相信我在 45 秒内运行了一个查询,然后我删除了这个函数,然后结果是 0 秒 :)

所以检查 udf_BUPDEF 没有做任何查询。

于 2008-12-10T06:00:25.060 回答
1

分解查询,使其成为一个简单的交叉连接。


   SELECT  CC.COST_CTR_NUM, GL.ACCOUNT_NO
              ,CC.COST_CTR_NUM AS CA_COSTCENT
              ,GL.ACCOUNT_NO AS CA_GLACCOUNT
              ,GL.LI_LNTM AS CA_LNTM
-- I don't know what is BUPDEF doing? but remove it from the query for time being
--              ,udf_BUPDEF(GL.ACCOUNT_NO, CC.COST_CTR_NUM, GL.LI_LNTM, 'N') AS CA_UNIT
       FROM   JOINGLAC AS GL
       CROSS JOIN COSTCENT AS CC

看看简单的交叉连接有多好?(没有应用任何功能)

于 2008-12-10T05:08:24.730 回答