2008-12-10 160 views
2

我正在移植一个创建两个表的MASSIVE CROSS JOIN的进程。生成的表格包含15m个记录(看起来像进程使用2600行表格和12000行表格进行30米交叉连接,然后进行一些分组,将其分成两半)。行相对较窄 - 只有6列。它已经运行了5个小时,没有完成的迹象。我只注意到已知的好东西和我期望的交叉连接之间的计数差异,所以我的输出没有将最终表格减半的分组或重复数 - 但这看起来好像不会完成任何操作时间很快。SQL Server 2005中的大规模CROSS JOIN

首先,我将着眼于从这个过程中删除这个表,如果可能的话 - 显然它可以通过单独连接到两个表来取代,但是现在我无法查看它在其他地方的使用情况。

但是,考虑到现有的流程(在较少的时间内,在功能较弱的机器上,使用FOCUS语言),是否有任何选项用于改进SQL Server(2005)中的大型文件系统的性能(硬件是不是一个真正的选择,这个盒子是一个32位的32位RAM的64位8路)?

详情:

这是写在FOCUS这样(我试图产生相同的输出,这是一个跨在SQL 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 

根据如何该表随后被使用,它应该能够从工艺被淘汰,通过简单地加入到这两个原始表格都是用来构建它的。然而,这是一个非常大的移植工作,我可能在一段时间内找不到该表的使用情况,所以我想知道是否有任何技巧及时地处理这样的大表(特别是考虑到现有的FOCUS过程能够更迅速地完成)。这样我就可以验证替换查询的构建的正确性,然后再用视图或其他方法来分解它。

我也在考虑分解UDF和字符串操作,并首先执行CROSS JOIN来打破这个过程。

效果为止:

事实证明,该UDF的贡献做了很多(负面的)的性能。但是,在15米排交叉和30米排交叉之间似乎也有很大差异。我没有SHOWPLAN权限(boo hoo),所以我不知道改变索引后它使用的计划是好还是坏。我还没有重构它,但我期待整个桌子很快就会消失。

+1

“MASSIVE CROSS JOIN”该语法应该引入到SQL语言中。 :) – 2008-12-10 05:52:07

回答

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

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

 

    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 
 

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

+0

如果这工作得很快,请尝试只做SELECT(使用所应用的功能)并查看,如果仍然可以? – shahkalpesh 2008-12-10 05:11:00

+0

已发布搜索结果 – 2008-12-17 15:06:29

+0

UDF性能(它们是标量并且不访问表)是关键并且非常可怕 - 两个UDF每秒只能处理大约300行。我目前正在寻找解决方法。 – 2009-02-26 18:52:06

2

继续别人的说法,包含在select中使用查询的数据库函数总是使我的查询非常缓慢。关闭我的头顶,我相信我有一个查询在45秒内运行,然后我删除了该功能,然后结果是0秒:)

因此检查udf_BUPDEF没有做任何查询。