In oltre vent'anni di risoluzione dei problemi nelle applicazioni JDE personalizzate, vedo regolarmente form Find/BrowseTipo di maschera JDE utilizzata per ricercare e visualizzare record in una griglia. o Header DetailMaschera JDE che visualizza un record principale e i relativi dettagli correlati. che impiegano da quattro a otto secondi per il rendering semplicemente perché gli sviluppatori inseriscono fetch Table I/OOperazioni di lettura o scrittura dati tra l'applicazione e le tabelle del database. sincroni su F0101Tabella principale dell'Address Book (Anagrafica) in JD Edwards. o F4101Tabella principale dell'Item Master (Anagrafica Articoli) in JD Edwards. nell'evento Dialog Is InitializedEvento software eseguito all'apertura di una maschera, prima della sua visualizzazione.. Questo difetto di progettazione scavalca il mapping nativo database-to-grid del motore JDE, costringendo il server HTML ad attendere roundtrip serializzati del database prima di renderizzare il primo pixel.

Per risolvere questo problema, dobbiamo passare da un fetching procedurale sincrono a un differimento guidato dagli eventi. Analizzeremo un esempio concreto di Table I/O in una APPL JDEUn'applicazione interattiva all'interno del sistema JD Edwards EnterpriseOne. per evitare problemi di caricamento lento delle form, spostando i fetch di validazione secondaria fuori dall'inizializzazione della form e nell'evento Grid Record Is FetchedEvento che si attiva ogni volta che una riga di dati viene caricata nella griglia.. Questo singolo aggiustamento architetturale riduce regolarmente la latenza di lancio delle form interattive dal 75% all'80%, mantenendo pulito il thread pool JVMInsieme di thread gestiti dalla Java Virtual Machine per eseguire compiti in parallelo. del server HTML.

La Meccanica della Latenza di Caricamento delle Form

Quando un utente apre un'applicazione interattiva personalizzata, il motore JASJava Application Server, il componente che trasforma la logica JDE in interfaccia web. elabora il ciclo di vita della creazione della form in modo sequenziale. L'evento Dialog Is Initialized blocca completamente il thread del presentation layer finché ogni riga sincrona di Event Rules (ER)Linguaggio di programmazione visuale proprietario di JD Edwards. non termina l'esecuzione. Se i vostri sviluppatori trattano questo evento come un deposito per la logica di setup, il client HTML non può nemmeno iniziare a disegnare lo schermo.

L'esecuzione di più operazioni di Table I/O come loop 'Fetch Single' o 'Select/Fetch Next' su pesanti tabelle master come l'Address Book Master (F0101) o l'Item Master (F4101) durante questa fase di blocco crea un immediato collo di bottiglia nelle prestazioni. Ogni singolo fetch richiede un round-trip dal server HTML all'enterprise server, e poi al database server. Questo comportamento frammentato aggrava la latenza di rete, specialmente in topologie cloud ibrideInfrastrutture informatiche che combinano server locali (on-premise) e servizi cloud pubblici. dove i server database e HTML risiedono in sottoreti diverse.

Mentre avvengono questi round-trip del database, l'utente finale fissa un browser web vuoto o congelato. Il client HTML è bloccato in attesa che il motore JAS — e, nelle distribuzioni moderne, il server Application Interface Services (AIS)Server che facilita lo scambio di dati tra JDE e applicazioni esterne o mobile. — completi l'elaborazione sincrona dei metadati e restituisca il payloadIl contenuto informativo effettivo trasportato da un pacchetto di dati o una risposta API. di dati iniziale. Fino a quando quel payload non viene consegnato, il motore di rendering del browser non può eseguire il JavaScript lato client richiesto per disegnare i controlli della form.

Nei nostri audit di performance su sistemi legacy 9.1 aggiornati alla 9.2, una tipica APPL personalizzata non ottimizzata impiega da otto a dodici secondi per caricarsi quando esegue più di una dozzina di letture sequenziali del database prima di renderizzare la form. Sostituire queste letture sequenziali con logica set-based o lazy loadingStrategia che ritarda il caricamento di un oggetto fino al momento in cui è effettivamente necessario. è il modo più rapido per far scendere i tempi di caricamento della form sotto la soglia di uno o due secondi.

Isolare il Table IO dalle Performance del Database

Vedo regolarmente sviluppatori sprecare giorni a ottimizzare gli indici del database su tabelle ad alto volume come la F0911 o la F4111 per risolvere una schermata lenta. Presumono che se l'inizializzazione di una form è lenta, il database debba avere difficoltà a trovare i record. La realtà è controintuitiva: il database spesso performa perfettamente, ma il volume di round-trip sequenziali tra l'Enterprise Server e il motore del database sta uccidendo le prestazioni. Se un'applicazione personalizzata esegue un Fetch Single all'interno di un loop centinaia di volte durante l'avvio, anche una lettura di indice altamente ottimizzata che richiede pochi millisecondi si aggrega in un ritardo di più secondi prima che la griglia venga caricata.

Questo squilibrio di latenza crea un classico scollamento tra DBADatabase Administrator, il professionista responsabile della gestione e ottimizzazione dei database. e sviluppatori JDE. Il vostro amministratore di database guarderà Oracle Database o SQL Server ProfilerStrumento di diagnostica per monitorare e analizzare le attività eseguite su un database SQL Server. e riporterà zero problemi, indicando un basso utilizzo della CPU e tempi di esecuzione inferiori al millisecondo. Nel frattempo, i log del server HTML JDE e i file jas.logFile di log che registra le attività e gli errori del server HTML JDE. mostrano tempi trascorsi enormi per il CallObject KernelProcesso server responsabile dell'esecuzione delle funzioni di business (BSFN). dell'applicazione associata. Il collo di bottiglia non è la velocità di recupero dei dati a livello di disco; è l'overhead di rete e middlewareSoftware che funge da intermediario tra diverse applicazioni, strumenti o database. per la gestione di migliaia di singole operazioni di database in modo seriale.

Per superare questo collo di bottiglia architetturale, è necessario eliminare l'elaborazione riga per riga durante l'evento Dialog Is Initialized. Invece di eseguire singole istruzioni Table I/O all'interno di un loop di Event Rules, rifattorizzate la logica per utilizzare l'elaborazione set-based o differite il caricamento dei dati ausiliari. Ad esempio, invece di interrogare i dati transazionali F4111 per ogni riga in una griglia da 500 record, caricate le chiavi univoche in una cache JDEArea di memoria temporanea utilizzata per memorizzare dati e velocizzare gli accessi successivi. una volta all'avvio della form, riducendo centinaia di round-trip del database a una singola ricerca alla velocità della memoria.

Posizionamento Strategico degli Eventi per il Table IO

Inserire cicli pesanti di Fetch Single nell'evento Dialog Is Initialized è il modo più rapido per bloccare una sessione client HTML per cinque o dieci secondi. In questa fase del motore runtime di JDE, il sistema sta ancora preparando il layout strutturale della form, il che significa che l'utente vede uno schermo vuoto mentre il database lavora. Spostare queste operazioni di database non bloccanti nell'evento Post Dialog Is InitializedEvento eseguito subito dopo l'inizializzazione, quando la maschera è quasi pronta per l'utente. assicura che la struttura della form venga renderizzata immediatamente, fornendo all'utente la conferma visiva che l'applicazione è reattiva.

Un fallimento architetturale comune nelle applicazioni JDE personalizzate è il recupero di dati ausiliari a livello di griglia durante il caricamento iniziale della form. Per una griglia che visualizza 50 record, l'esecuzione di ricerche individuali nelle tabelle durante l'inizializzazione forza dozzine di roundtrip sequenziali al database. Gli sviluppatori devono spostare questo lavoro negli eventi Grid Record is Fetched o Write Grid Line-Before, che vengono eseguiti dinamicamente man mano che ogni riga viene popolata. Ciò riduce la dimensione del payload iniziale e previene i timeout del server JAS.

Nelle form Find/Browse, gli sviluppatori spesso scrivono loop manuali Select e Fetch Next all'interno dell'evento del pulsante Find per filtrare i risultati della griglia. Questo scavalca la gestione integrata dei cursori del database del motore JDE. L'esecuzione della funzione di sistema Set SelectionFunzione JDE utilizzata per aggiungere filtri personalizzati a una query di database. all'interno dell'evento Clear Screen Before Find consente al motore nativo JDE di aggiungere clausole WHERE personalizzate direttamente all'istruzione SELECT primaria, lasciando che l'indice del database faccia il lavoro pesante.

Per le form header/detail multi-scheda, caricare i record delle tabelle figlio per tutte le schede durante l'apertura iniziale è una tassa sulle prestazioni non necessaria. In una schermata standard di inserimento F4211Tabella che contiene le righe di dettaglio degli ordini di vendita in JD Edwards. o F4311, un utente potrebbe ispezionare le schede secondarie solo in una piccola frazione di sessioni, tipicamente meno del 15%. L'implementazione del fetching condizionale — dove le letture dettagliate su tabelle come F42119 vengono attivate solo quando l'utente clicca su una specifica pagina della scheda — riduce l'overhead di esecuzione SQL iniziale a una singola query leggera.

Optimized Form Load Event Sequence

Rifattorizzazione di un Esempio di Table IO in una APPL Personalizzata

Recentemente ho revisionato un'applicazione di interrogazione ordini aperti F4211 personalizzata in cui gli utenti riscontravano un ritardo fastidioso ogni volta che aprivano la form di ricerca. La causa principale era un classico anti-pattern JDE: lo sviluppatore aveva inserito un loop manuale Select/Fetch Next all'interno dell'evento Dialog Is Initialized per recuperare i nomi dei clienti dall'Address Book Master (F0101) e i codici di spiegazione fiscale dagli Address Book Phone Numbers (F0116) per ogni ordine di vendita nel sistema prima ancora che la griglia venisse renderizzata. Questo martellamento procedurale del database scavalca completamente l'efficienza del middleware EnterpriseOne.

Per risolvere il problema, abbiamo rimosso il Table I/O procedurale dalle event rules e rifattorizzato la business viewOggetto che definisce la selezione di campi e tabelle per un'applicazione JDE. primaria dell'applicazione. Sostituendo la vista piatta F4211 con una semplice left outer joinOperazione SQL che combina record di due tabelle includendo tutti i record della tabella sinistra. tra F4211 e F0101/F0116, il motore del database gestisce la join relazionale in una singola operazione SQL. Questo spostamento di design delega il lavoro pesante all'ottimizzatore di query del database, eliminando centinaia di singoli roundtrip di rete tra il server HTML, l'enterprise server e il database server.

Quando una join complessa tra tabelle non è fattibile a causa di mapping tra diversi datasourceConfigurazione che indica al sistema dove risiedono fisicamente i dati (database o server). o logiche di business personalizzate volatili, la soluzione corretta è spostare il Table I/O nell'evento Grid Record is Fetched. A differenza degli eventi di inizializzazione che elaborano l'intero dataset in anticipo, questo evento viene eseguito in modalità lazy, attivandosi solo per le righe attualmente visibili a schermo. Se la dimensione della pagina della griglia è impostata sui 50 record standard, JDE eseguirà esattamente 50 fetch invece di scansionare l'intera tabella F4211.

L'applicazione di questo pattern di rifattorizzazione alla form di interrogazione F4211 ha prodotto risultati immediati e misurabili. Il tempo di caricamento iniziale della form è sceso da oltre sei secondi a meno di mezzo secondo per una pagina di griglia standard da 50 righe. Questo semplice cambiamento riduce drasticamente l'utilizzo del thread pool del database sul vostro enterprise server, liberando risorse per gli utenti interattivi simultanei in tutta l'istanza HTML.

Synchronous vs. Deferred Loading Performance

Ottimizzazione del Caricamento della Griglia e Tabelle Virtuali

Gli sviluppatori spesso trascurano la proprietà della griglia "Page-at-a-Time", ottenendo APPL che tentano di estrarre decine di migliaia di record dalla F4211 nella memoria del server web HTML al lancio iniziale. L'abilitazione dell'elaborazione Page-at-a-TimeProprietà della griglia JDE che carica i dati a blocchi invece di scaricarli tutti insieme. limita il fetch iniziale del database alla dimensione della pagina della griglia — tipicamente da 10 a 20 righe — e interroga i record successivi solo quando l'utente clicca sul pulsante "Next". Questo singolo cambio di proprietà stabilizza immediatamente l'uso della memoria JVM sulle vostre istanze WebLogicServer applicativo Java di Oracle utilizzato per ospitare l'ambiente web di JD Edwards. o WebSphere durante i picchi di attività mattutina.

Le Business View standard di JDE falliscono quando sono necessarie join multi-tabella complesse, query union o aggregazioni su tabelle come F4101, F41021 e F4102. Invece di scrivere istruzioni Table I/O nidificate all'interno dell'evento Grid Record is Fetched per risolvere questi campi, dovreste costruire una vista database nativa a livello di SQL Server o Oracle Database e mapparla come una tabella virtuale JDE tramite l'Object Management Workbench (OMW)Lo strumento principale per lo sviluppo, gestione e distribuzione degli oggetti in JD Edwards.. Questa tabella virtuale consente al middleware del database JDE di eseguire una singola istruzione SQL altamente ottimizzata invece di costringere il server JAS a coordinare più operazioni Table I/O sequenziali.

Consolidare il layer di accesso ai dati in una tabella virtuale riduce i round-trip del database dall'80% al 90% su schermate transazionali ad alto volume come l'inserimento di ordini di vendita personalizzati o le APPL di ricerca inventario. In un progetto recente, la sostituzione di più fetch Table I/O nidificati in F41021 e F4105 con una singola tabella virtuale ha ridotto il tempo di caricamento di una schermata di interrogazione personalizzata da oltre otto secondi a meno di mezzo secondo. Questo approccio sposta il lavoro pesante di indicizzazione e join al motore del database, dove appartiene, mantenendo il motore logico di EnterpriseOne pulito e reattivo.

Profilazione del Caricamento delle Form con Server Manager

Risolvere un ritardo di caricamento della form di diversi secondi richiede di superare le congetture e aprire il file jdedebug.logFile di log dettagliato utilizzato per il debug tecnico e l'analisi delle query SQL.. Questo log è il vostro principale strumento diagnostico per identificare le esatte istruzioni Table I/O che stanno rallentando l'interfaccia utente. Avviando una traccia CallObject Kernel all'interno di Server Manager, è possibile catturare l'esatta durata in millisecondi di ogni istruzione SQL eseguita durante gli eventi Dialog is Initialized e Post Dialog is Initialized. Questo tracciamento in tempo reale espone l'overhead di elaborazione delle business function personalizzate prima ancora che la form venga renderizzata sullo schermo dell'utente.

Analizzando la traccia, cercate pattern ripetuti di SELECT ... FROM PRODDTA.F0101 o PRODDTA.F4101 che si verificano nello stesso secondo, ognuno dei quali interroga diversi numeri di address book o articoli. Questo pattern indica un loop che esegue Table I/O su base riga per riga della griglia, invece di utilizzare un singolo fetch set-based o una vista database. L'eliminazione di queste chiamate SQL iterative può comprimere immediatamente un ritardo del database di mezzo secondo a pochi millisecondi, riducendo drasticamente il tempo trascorso nel CallObject Kernel.

Una volta rifattorizzati gli eventi incriminati, è necessario consolidare questi guadagni prima del prossimo aggiornamento della Tools ReleaseVersione dell'architettura tecnica di base (middleware) di JD Edwards EnterpriseOne.. Utilizzate l'applicazione Performance Monitor (P980060) per stabilire una chiara baseline di elaborazione delle transazioni per le vostre applicazioni interattive critiche. Il confronto di queste metriche pre- e post-aggiornamento previene le regressioni, assicurando che un aggiornamento Tools alla 9.2.8 o successiva non reintroduca silenziosamente latenza attraverso comportamenti alterati del middleware o modifiche ai driver del database. Eseguite questi test di benchmark sotto un carico simulato di 50 utenti simultanei per verificare la stabilità delle vostre modifiche.

Se state rifattorizzando codice APPL legacy per soddisfare gli standard di performance della 9.2.8, le nostre altre guide tecniche sulla gestione della cache BSFNBusiness Function, moduli di codice che eseguono operazioni logiche o calcoli complessi. e sulle estensioni delle form basate su AIS offrono approfondimenti sull'ottimizzazione degli ambienti EnterpriseOne.