我正在移植一个创建两个表的MASSIVE CROSS JOIN
的进程。结果表包含15m记录(看起来该进程使用2600行表和12000行表进行30m交叉连接,然后执行一些必须将其拆分为一半的分组)。行相对较窄 - 只有6列。它已经运行了5个小时,没有完成的迹象。我只是注意到已知商品与我期望的交叉连接之间的计数差异,所以我的输出没有分组或重复数据删除,这将使决赛桌减半 - 但这似乎仍然无法完成任何时间很快。
首先,我将尽可能地从流程中删除此表 - 显然可以通过单独连接到两个表来替换它,但是现在我无法看到它所使用的其他任何地方。 / p>
但是考虑到现有的流程(在较短的时间内,在功能较弱的机器上,使用FOCUS语言),是否有任何选项可以提高SQL Server(2005)中大CROSS JOIN
的性能(硬件实际上不是一个选项,这个盒子是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
这样的大表的任何技巧(特别是鉴于FOCUS中的现有流程能够更快地完成。)这样我就可以验证构建替换查询的正确性,然后将其与视图或其他任何因素一起分解。
我也在考虑将UDF和字符串操作分解出来并首先执行CROSS JOIN以稍微打破这个过程。
结果如此:
事实证明,UDF对性能的贡献很大(负面)。但是,15米行交叉连接和30米交叉连接之间似乎也存在很大差异。我没有SHOWPLAN权限(boo hoo),所以在更改索引后我无法判断它正在使用的计划是好还是坏。我还没有对它进行重构,但我希望整个桌子不久就会消失。
答案 0 :(得分: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上有任何触发器吗?索引怎么样?如果插入这么大,您将要删除该表上的所有触发器和索引。
答案 1 :(得分:2)
继续其他人的说法,包含查询中使用的查询的数据库函数总是使我的查询非常慢。在我的头顶,我相信我有一个查询运行45秒,然后我删除了该功能,然后结果是0秒:))
所以检查udf_BUPDEF没有做任何查询。
答案 2 :(得分: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
看看简单的交叉连接有多好? (没有应用任何功能)