Question

Je suis le portage d'un processus qui crée un MASSIVES de deux CROSS JOIN tables. Le tableau résultant contient les enregistrements 15m (ressemble le processus fait une croix de 30 m se joindre à une table de 2600 lignes et une table 12000 de ligne et fait alors un certain groupe qui doit le diviser en deux). Les lignes sont relativement étroites - seulement 6 colonnes. Il a été en cours d'exécution pendant 5 heures avec aucun signe d'achèvement. Je viens juste remarqué la différence de comptage entre le connu bien et ce que j'attendre pour la jointure croisée, de sorte que ma sortie n'a pas le groupement ou deduping qui réduira de moitié la table finale - mais cela semble encore comme ça ne va pas à remplir tout si tôt.

D'abord, je vais chercher à éliminer ce tableau du processus si possible - de toute évidence, il pourrait être remplacé en se joignant aux deux tables individuellement, mais qui ont en ce moment je ne suis pas la visibilité partout ailleurs dans il est utilisé <. / p>

Mais étant donné que le processus existant, il ne (en moins de temps, sur une machine moins puissante, en utilisant le langage FOCUS), sont-il des options pour améliorer les performances des grandes s dans SQL <=> Server (2005) (matériel est pas vraiment une option, cette case est un 64 bits 8 voies avec 32 Go de RAM)?

Détails:

Il est écrit de cette façon dans FOCUS (je suis en train de produire la même sortie, qui est une CROSS JOIN dans SQL):

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

Ainsi, la sortie requise est vraiment une CROSS JOIN (il est de rejoindre une colonne vide de chaque côté).

Dans 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]

Avec le code 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

Selon la façon dont ce tableau est ensuite utilisé, il devrait pouvoir être éliminé du processus, en se joignant simplement à la fois les tables d'origine utilisées pour le construire. Cependant, ceci est un effort de portage extrêmement important, et je pourrais trouver pas l'utilisation de la table pendant un certain temps, donc je me demandais s'il y avait des astuces pour les grandes tables <=> ing comme ça en temps voulu (en particulier étant donné que le processus existant FOCUS est en mesure de le faire plus rapidement). De cette façon, je pouvais valider la justesse de mon immeuble de la requête de remplacement, puis facteur plus tard, avec des vues ou autre.

Je suis également envisage d'affacturage la manipulation des cordes et des FDU et effectuer la CROSS JOIN premier à briser le processus un peu.

résultats obtenus jusqu'à présent:

Il se trouve que les UDFs contribuent beaucoup (négativement) à la performance. Mais il semble aussi y avoir une grande différence entre une croix rangée de 15m rejoignent et une croix de 30 mètres de la ligne rejoindre. Je ne dispose pas des droits SHOWPLAN (boo hoo), je ne peux pas dire si le plan qu'il utilise est meilleur ou pire après avoir changé les index. Je ne l'ai pas encore refondus, mais je attends la table entière à aller sous peu.

Était-ce utile?

La solution

l'examen de cette requête montre seulement une colonne utilisée d'une table, et seulement deux colonnes utilisées à partir de l'autre table. En raison du nombre très bas de colonnes utilisées, cette requête peut être facilement améliorée avec des indices couvrant:

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

Voici mes questions pour une optimisation plus poussée:

Lorsque vous mettez la requête dans l'Analyseur de requêtes et Whack le bouton « Afficher estimé plan d'exécution », il affichera une représentation graphique de ce qu'il va faire.

Type de jointure: Il devrait y avoir une jointure à boucles imbriquées là-dedans. (Les autres options sont fusion JOIN et hachage). Si vous voyez boucle imbriquée, puis sur OK. Si vous voyez jointure de fusion ou jointure de hachage, laissez-nous savoir.

Ordre de l'accès de table: Allez tout le chemin vers le haut et faire défiler tout le chemin vers la droite. La première étape doit être accès à une table. Quelle table est que, et quelle est la méthode utilisée (scan d'index, scan index ordonné en clusters)? Quelle est la méthode utilisée pour accéder à l'autre table?

Parallélisme: Vous devriez voir les petites flèches jaggedy sur presque toutes les icônes dans le plan indiquant que le parallélisme est utilisé. Si vous ne voyez pas cela, il y a un problème majeur!

Ce udf_BUPDEF me préoccupe. Est-il lire des tables supplémentaires? Util.PADLEFT me concerne moins, mais quand même .. quel est-il? Si ce n'est pas un objet de base de données, puis envisager d'utiliser ceci:

RIGHT('z00000000000000000000000000' + columnName, 7)

Y a-t-il des déclencheurs sur JOINCCAC? Que diriez-vous des indices? Avec un insert ce grand, vous aurez envie de laisser tomber tous les déclencheurs et les index sur la table.

Autres conseils

En continuant sur ce que d'autres un dicton, les fonctions DB qui contenait des requêtes qui sont utilisées dans une sélection toujours fait mes requêtes extrêmement lent. Du haut de ma tête, je crois que j'avais une requête exécutée en 45 secondes, puis je l'ai enlevé la fonction, puis résulta 0 secondes:)

Alors vérifier udf_BUPDEF ne fait pas des questions.

Décomposer la requête pour en faire une simple croix simple jointure.


   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

Voir Quelle est la simple croix rejoindre? (Sans les fonctions appliquées sur elle)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top