Maggiore statistica del sito nel tuo piccolo archivio

Analizzando le statistiche del sito, otteniamo un'idea di ciò che sta accadendo. Confrontiamo i risultati con altre conoscenze sul prodotto o servizio, migliorando così la nostra esperienza.

Una volta completata l'analisi dei primi risultati e riflettuta sull'informazione raccolta, inizia la fase successiva. Nascono idee: e se guardassimo i dati da un'altra prospettiva?

In questa fase ci sono limitazioni degli strumenti di analisi. Questa è una delle ragioni per cui Google Analytics non era sufficiente per me, a causa della sua capacità limitata di visualizzare e manipolare i propri dati.

Ho sempre desiderato caricare rapidamente i dati di base (master data), aggiungere un altro livello di aggregazione o interpretare diversamente i valori esistenti.

È facile farlo in il proprio piccolo deposito basato sul file access.log, e per questo è sufficiente il linguaggio SQL.

Quindi, quali domande desidero rispondere?

Cosa e quando è stato modificato sul sito

La storia delle modifiche ai dati di base (master data) è sempre di interesse.

Maggiore statistica del sito nel tuo piccolo archivio

Richiesta SQL del report

SELECT
	1 as 'SideStackedBar: Aggiornamenti dei contenuti per mese',
	strftime('%m/%Y', datetime(UPDATE_DT, 'unixepoch')) AS 'Mese',
	COUNT(CASE WHEN PAGE_TITLE != 'n.a.' THEN DIM_REQUEST_ID END) AS 'Aggiornamenti delle pagine web',
	COUNT(CASE WHEN PAGE_DESCR = 'IMAGES' THEN DIM_REQUEST_ID END) AS 'Caricamenti di immagini',
	COUNT(CASE WHEN PAGE_DESCR = 'VIDEO' THEN DIM_REQUEST_ID END) AS 'Caricamenti video',
	COUNT(CASE WHEN PAGE_DESCR = 'AUDIO' THEN DIM_REQUEST_ID END) AS 'Caricamenti audio'
FROM DIM_REQUEST
WHERE PAGE_TITLE != 'n.a.' OR PAGE_DESCR != 'n.a.'
GROUP BY strftime('%m/%Y', datetime(UPDATE_DT, 'unixepoch'))
ORDER BY UPDATE_DT

Ad esempio, in un certo momento sono state effettuate ottimizzazioni SEO o è stato aggiunto nuovo contenuto al sito, e di conseguenza ci si aspetta un aumento del traffico.

Gruppi di utenti

Il più semplice esempio di gruppo può essere rappresentato da un agente utente o dal sistema operativo utilizzato.

La misurazione degli agenti utente ha accumulato circa mille registrazioni e mi interessava vedere la dinamica della distribuzione degli agenti all'interno del gruppo.

Maggiore statistica del sito nel tuo piccolo archivio

Richiesta SQL del report

SELECT
	1 AS 'SideStackedBar: Agenti Utente',
	AGENT_OS AS 'OS',
	SUM(CASE WHEN AGENT_BOT = 'n.a.' THEN 1 ELSE 0 END ) AS 'Agente Utente di Utenti',
	SUM(CASE WHEN AGENT_BOT != 'n.a.' THEN 1 ELSE 0 END ) AS 'Agente Utente di Bot'
FROM DIM_USER_AGENT
WHERE DIM_USER_AGENT_ID != -1
GROUP BY AGENT_OS
ORDER BY 3 DESC

La maggior parte delle varie combinazioni di agenti proviene dal mondo Windows. Tra quelle non definite ci sono anche nomi come WhatsApp, PocketImageCache, PlayStation, SmartTV e simili.

Attività dei gruppi utenti per settimana

Unendo alcuni gruppi, è possibile osservare la distribuzione della loro attività.

Ad esempio, gli utenti del cluster Linux consumano più traffico sul sito rispetto a tutti gli altri.

Maggiore statistica del sito nel tuo piccolo archivio

Richiesta SQL del report

SELECT
1 as 'StackedBar: Volume di traffico per sistema operativo utente e per settimana',
strftime('%W week', datetime(FCT.EVENT_DT, 'unixepoch')) AS 'Settimana',
SUM(CASE WHEN USG.AGENT_OS IN ('Android', 'Linux') THEN FCT.BYTES ELSE 0 END)/1000 AS 'Utenti Android/Linux',
SUM(CASE WHEN USG.AGENT_OS IN ('Windows') THEN FCT.BYTES ELSE 0 END)/1000 AS 'Utenti Windows',
SUM(CASE WHEN USG.AGENT_OS IN ('Macintosh', 'iOS') THEN FCT.BYTES ELSE 0 END)/1000 AS 'Utenti Mac/iOS',
SUM(CASE WHEN USG.AGENT_OS IN ('n.a.', 'BlackBerry') THEN FCT.BYTES ELSE 0 END)/1000 AS 'Altro'
FROM
  FCT_ACCESS_USER_AGENT_DD FCT,
  DIM_USER_AGENT USG,
  DIM_HTTP_STATUS HST
WHERE FCT.DIM_USER_AGENT_ID=USG.DIM_USER_AGENT_ID
  AND FCT.DIM_HTTP_STATUS_ID = HST.DIM_HTTP_STATUS_ID
  AND USG.AGENT_BOT = 'n.a.' /* solo utenti */
  AND HST.STATUS_GROUP IN ('Successful') /* pagine valide */
  AND datetime(FCT.EVENT_DT, 'unixepoch') > date('now', '-3 month')
GROUP BY strftime('%W week', datetime(FCT.EVENT_DT, 'unixepoch'))
ORDER BY FCT.EVENT_DT

Consumo intenso di traffico

Dalla tabella si possono vedere i gruppi di utenti più attivi e il giorno della loro attività.
I più attivi appartengono al cluster Linux.

Maggiore statistica del sito nel tuo piccolo archivio

Richiesta SQL del report

SELEZIONA
1 AS 'Tabella: Agente Utente con Elevato Utilizzo',
strftime('%d.%m.%Y', datetime(FCT.EVENT_DT, 'unixepoch')) AS 'Giorno',
ROUND(1.0*SUM(FCT.BYTES)/1000000, 1) AS 'Traffico MB',
ROUND(1.0*SUM(FCT.IP_CNT)/SUM(1), 1) AS 'IPs',
ROUND(1.0*SUM(FCT.REQUEST_CNT)/SUM(1), 1) AS 'Richieste',
USA.DIM_USER_AGENT_ID AS 'ID',
MAX(USA.USER_AGENT_NK) AS 'Agente Utente',
MAX(USA.AGENT_BOT) AS 'Bot'
DA
FCT_ACCESS_USER_AGENT_DD FCT,
DIM_USER_AGENT USA
DOVE FCT.DIM_USER_AGENT_ID = USA.DIM_USER_AGENT_ID
  E datetime(FCT.EVENT_DT, 'unixepoch') >= date('now', '-30 day')
GRUPPA PER USA.DIM_USER_AGENT_ID, strftime('%d.%m.%Y', datetime(FCT.EVENT_DT, 'unixepoch')) 
ORDINA PER SUM(FCT.BYTES) DESC, FCT.EVENT_DT
LIMIT 10

Utilizzando gli attributi giorno e ID dell'agente, è possibile trovare rapidamente e monitorare le statistiche sui giorni di gruppi specifici di utenti. Se necessario, è possibile trovare rapidamente informazioni dettagliate nella tabella di staging.

Come ottenere informazioni?

Le informazioni dal file access.log possono diventare ancora più efficaci se integrati ulteriori fonti di dati, introducendo nuovi livelli di aggregazione e raggruppamento.

Dati e entità di base

I dati di base comprendono informazioni su entità: pagine web, immagini, contenuti video e audio, e nel caso di un negozio — prodotti.

Le entità stesse fungono da misurazioni e il processo di salvataggio delle modifiche degli attributi è chiamato storicizzazione. In un database, questo processo è spesso implementato sotto forma di misurazioni a cambiamento lento (SCD).

Le fonti dei dati di base possono provenire da vari sistemi, quindi quasi sempre è necessario integrarli.

Misurazione a cambiamento lento

La misurazione DIM_REQUEST conterrà informazioni sulle richieste al sito in forma storica.

Tabella SCD2

CREATE TABLE DIM_REQUEST ( /* tabella scd per le richieste degli utenti */
  DIM_REQUEST_ID      INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
  DIM_REQUEST_ID_HIST INTEGER NOT NULL DEFAULT -1,
  REQUEST_NK          TEXT NOT NULL DEFAULT 'n.a.', /* richiesta senza ?parametri */
  PAGE_TITLE          TEXT NOT NULL DEFAULT 'n.a.',
  PAGE_DESCR          TEXT NOT NULL DEFAULT 'n.a.',
  PAGE_KEYWORDS       TEXT NOT NULL DEFAULT 'n.a.',
  DELETE_FLAG         INTEGER NOT NULL DEFAULT 0,
  UPDATE_DT           INTEGER NOT NULL DEFAULT 0,
  UNIQUE (REQUEST_NK, DIM_REQUEST_ID_HIST)
);
INSERT INTO DIM_REQUEST (DIM_REQUEST_ID) VALUES (-1);

In aggiunta, creeremo una vista che mostri sempre tutte le registrazioni nell'ultimo stato. Necessaria per il caricamento della misurazione stessa.

Maggiore statistica del sito nel tuo piccolo archivio

Vista attuale SCD2

/* Content: actual view on scd table */
SELECT HI.DIM_REQUEST_ID,
  HI.DIM_REQUEST_ID_HIST,
  HI.REQUEST_NK,
  HI.PAGE_TITLE,
  HI.PAGE_DESCR,
  HI.PAGE_KEYWORDS,
  NK.CNT AS HIST_CNT,
  HI.DELETE_FLAG,
  strftime('%d.%m.%Y %H:%M', datetime(HI.UPDATE_DT, 'unixepoch')) AS UPDATE_DT
FROM
  ( SELECT REQUEST_NK, MAX(DIM_REQUEST_ID) AS DIM_REQUEST_ID, SUM(1) AS CNT
    FROM DIM_REQUEST
    GROUP BY REQUEST_NK
  ) NK,
  DIM_REQUEST HI
WHERE 1 = 1
  AND NK.REQUEST_NK = HI.REQUEST_NK
  AND NK.DIM_REQUEST_ID = HI.DIM_REQUEST_ID;

E una vista in cui per ogni registrazione è raccolta l'informazione storica. Necessaria per costruire un collegamento storicamente corretto con i fatti.

Maggiore statistica del sito nel tuo piccolo archivio

Rappresentazione storica SCD2

/* Content: actual view on scd table */
SELECT SCD.DIM_REQUEST_ID,
  SCD.DIM_REQUEST_ID_HIST,
  SCD.REQUEST_NK,
  SCD.PAGE_TITLE,
  SCD.PAGE_DESCR,
  SCD.PAGE_KEYWORDS,
  SCD.DELETE_FLAG,
  CASE
    WHEN HIS.UPDATE_DT IS NULL
    THEN 1
    ELSE 0 END ACTIVE_FLAG,
  SCD.DIM_REQUEST_ID_HIST AS ID_FROM,
  SCD.DIM_REQUEST_ID AS ID_TO,
  CASE
    WHEN SCD.DIM_REQUEST_ID_HIST=-1
    THEN 3600
    ELSE IFNULL(SCD.UPDATE_DT,3600)
  END AS TIME_FROM,
  CASE
    WHEN HIS.UPDATE_DT IS NULL
    THEN 253370764800
    ELSE HIS.UPDATE_DT
  END AS TIME_TO,
  CASE
    WHEN SCD.DIM_REQUEST_ID_HIST=-1
    THEN STRFTIME('%d.%m.%Y %H:%M', DATETIME(3600, 'unixepoch'))
    ELSE STRFTIME('%d.%m.%Y %H:%M', DATETIME(IFNULL(SCD.UPDATE_DT,3600), 'unixepoch'))
  END AS ACTIVE_FROM,
  CASE
    WHEN HIS.UPDATE_DT IS NULL
    THEN STRFTIME('%d.%m.%Y %H:%M', DATETIME(253370764800, 'unixepoch'))
    ELSE STRFTIME('%d.%m.%Y %H:%M', DATETIME(HIS.UPDATE_DT, 'unixepoch'))
  END AS ACTIVE_TO
FROM
  DIM_REQUEST SCD
  LEFT OUTER JOIN DIM_REQUEST HIS
  ON SCD.REQUEST_NK = HIS.REQUEST_NK AND SCD.DIM_REQUEST_ID = HIS.DIM_REQUEST_ID_HIST;

Aggregazione dei dati

La compressione (aggregazione) consente di valutare i dati a un livello superiore e di rilevare anomalie e tendenze che non sono visibili nei rapporti dettagliati.

Ad esempio, nell'insieme di misurazioni con i codici di stato delle richieste DIM_HTTP_STATUS aggiungeremo un gruppo:

STATUS / GRUPPO
0xx / n.a.
1xx / Informativo
2xx / Riuscito
3xx / Reindirizzamento
4xx / Errore del Client
5xx / Errore del Server

L'insieme di misurazioni degli agenti utente DIM_USER_AGENT conterrà gli attributi AGENT_OS e AGENT_BOT, responsabili dei gruppi. Questi possono essere popolati durante il processo ETL:

Caricamento DIM_USER_AGENT

/* Propagate the user agent from access log */
INSERT INTO DIM_USER_AGENT (USER_AGENT_NK, AGENT_OS, AGENT_ENGINE, AGENT_DEVICE, AGENT_BOT, UPDATE_DT)
WITH CLS AS (
	SELECT BROWSER
	FROM STG_ACCESS_LOG WHERE LENGTH(BROWSER)>1
	GROUP BY BROWSER
)
SELECT
	CLS.BROWSER AS USER_AGENT_NK,
	CASE
	WHEN INSTR(CLS.BROWSER,'Macintosh')>0
		THEN 'Macintosh'
	WHEN INSTR(CLS.BROWSER,'iPhone')>0
			 OR INSTR(CLS.BROWSER,'iPad')>0
			 OR INSTR(CLS.BROWSER,'iPod')>0
			 OR INSTR(CLS.BROWSER,'Apple TV')>0
			 OR INSTR(CLS.BROWSER,'Darwin')>0
		THEN 'iOS'
	WHEN INSTR(CLS.BROWSER,'Android')>0
		THEN 'Android'
	WHEN INSTR(CLS.BROWSER,'X11;')>0 OR INSTR(CLS.BROWSER,'Wayland;')>0 OR INSTR(CLS.BROWSER,'linux-gnu')>0
		THEN 'Linux'
	WHEN INSTR(CLS.BROWSER,'BB10;')>0 OR INSTR(CLS.BROWSER,'BlackBerry')>0
		THEN 'BlackBerry'
	WHEN INSTR(CLS.BROWSER,'Windows')>0
		THEN 'Windows'
	ELSE 'n.a.' END AS AGENT_OS, -- OS
	CASE
	WHEN INSTR(CLS.BROWSER,'AppleCoreMedia')>0
		THEN 'AppleWebKit'
	WHEN INSTR(CLS.BROWSER,') ')>1 AND LENGTH(CLS.BROWSER)>INSTR(CLS.BROWSER,') ')
		THEN COALESCE(SUBSTR(CLS.BROWSER, INSTR(CLS.BROWSER,') ')+2, LENGTH(CLS.BROWSER) - INSTR(CLS.BROWSER,') ')-1), 'N/A')
	ELSE 'n.a.' END AS AGENT_ENGINE, -- Engine
	CASE
	WHEN INSTR(CLS.BROWSER,'iPhone')>0
		THEN 'iPhone'
	WHEN INSTR(CLS.BROWSER,'iPad')>0
		THEN 'iPad'
	WHEN INSTR(CLS.BROWSER,'iPod')>0
		THEN 'iPod'
	WHEN INSTR(CLS.BROWSER,'Apple TV')>0
		THEN 'Apple TV'
	WHEN INSTR(CLS.BROWSER,'Android ')>0 AND INSTR(CLS.BROWSER,'Build')>0
		THEN COALESCE(SUBSTR(CLS.BROWSER, INSTR(CLS.BROWSER,'Android '), INSTR(CLS.BROWSER,'Build')-INSTR(CLS.BROWSER,'Android ')), 'n.a.')
	WHEN INSTR(CLS.BROWSER,'Android ')>0 AND INSTR(CLS.BROWSER,'MIUI')>0
		THEN COALESCE(SUBSTR(CLS.BROWSER, INSTR(CLS.BROWSER,'Android '), INSTR(CLS.BROWSER,'MIUI')-INSTR(CLS.BROWSER,'Android ')), 'n.a.')
	ELSE 'n.a.' END AS AGENT_DEVICE, -- Device
	CASE
	WHEN INSTR(LOWER(CLS.BROWSER),'yandex.com')>0
		THEN 'yandex'
	WHEN INSTR(LOWER(CLS.BROWSER),'googlebot')>0
		THEN 'google'
	WHEN INSTR(LOWER(CLS.BROWSER),'bingbot')>0
		THEN 'microsoft'
	WHEN INSTR(LOWER(CLS.BROWSER),'ahrefsbot')>0
		THEN 'ahrefs'
	WHEN INSTR(LOWER(CLS.BROWSER),'jobboersebot')>0 OR INSTR(LOWER(CLS.BROWSER),'jobkicks')>0
		THEN 'job.de'
	WHEN INSTR(LOWER(CLS.BROWSER),'mail.ru')>0
		THEN 'mail.ru'
	WHEN INSTR(LOWER(CLS.BROWSER),'baiduspider')>0
		THEN 'baidu'
	WHEN INSTR(LOWER(CLS.BROWSER),'mj12bot')>0
		THEN 'majestic-12'
	WHEN INSTR(LOWER(CLS.BROWSER),'duckduckgo')>0
		THEN 'duckduckgo'
	WHEN INSTR(LOWER(CLS.BROWSER),'bytespider')>0
		THEN 'bytespider'
	WHEN INSTR(LOWER(CLS.BROWSER),'360spider')>0
		THEN 'so.360.cn'
	WHEN INSTR(LOWER(CLS.BROWSER),'compatible')>0 OR INSTR(LOWER(CLS.BROWSER),'http')>0
		OR INSTR(LOWER(CLS.BROWSER),'libwww')>0 OR INSTR(LOWER(CLS.BROWSER),'spider')>0
		OR INSTR(LOWER(CLS.BROWSER),'java')>0 OR INSTR(LOWER(CLS.BROWSER),'python')>0
		OR INSTR(LOWER(CLS.BROWSER),'robot')>0 OR INSTR(LOWER(CLS.BROWSER),'curl')>0 OR INSTR(LOWER(CLS.BROWSER),'wget')>0
		THEN 'other'
	ELSE 'n.a.' END AS AGENT_BOT, -- Bot
	STRFTIME('%s','now') AS UPDATE_DT
FROM CLS
LEFT OUTER JOIN DIM_USER_AGENT TRG
ON CLS.BROWSER = TRG.USER_AGENT_NK
WHERE TRG.DIM_USER_AGENT_ID IS NULL

Integrazione dei dati

Include l'organizzazione del trasferimento dati dal sistema operativo al rapporto. A tal fine, è necessario creare una tabella di staging con una struttura simile a quella della sorgente.

Nella staging, le informazioni sulle pagine web vengono trasferite dal backup del CMS sotto forma di richieste di inserimento.

Il caricamento della tabella storica DIM_REQUEST con i dati di base avviene in tre fasi: caricamento di nuove chiavi e attributi, aggiornamento di quelli esistenti e registrazione delle righe eliminate.

Caricamento di nuove righe SCD2

/* Load request table SCD from master data */
INSERT INTO DIM_REQUEST (DIM_REQUEST_ID_HIST, REQUEST_NK, PAGE_TITLE, PAGE_DESCR, PAGE_KEYWORDS, DELETE_FLAG, UPDATE_DT)
WITH CLS  AS ( -- prepare keys
	SELECT
	'/' || NAME AS REQUEST_NK,
	TITLE       AS PAGE_TITLE,
	CASE WHEN DESCRIPTION = '' OR DESCRIPTION IS NULL
	     THEN 'n.a.' ELSE DESCRIPTION
	END AS PAGE_DESCR,
	CASE WHEN KEYWORDS = '' OR KEYWORDS IS NULL
	     THEN 'n.a.' ELSE KEYWORDS
	END AS PAGE_KEYWORDS
	FROM STG_CMS_MENU
	WHERE CONTENT_TYPE != 'folder' -- only web pages
	  AND PAGE_TITLE != 'n.a.' -- master data which make sense
)
/* new records from stage: CLS */
SELECT
	-1 AS DIM_REQUEST_ID_HIST,
	CLS.REQUEST_NK,
	CLS.PAGE_TITLE,
	CLS.PAGE_DESCR,
	CLS.PAGE_KEYWORDS,
	0 AS DELETE_FLAG,
	STRFTIME('%s','now') AS UPDATE_DT
FROM CLS
LEFT OUTER JOIN
 (
	SELECT
	DIM_REQUEST_ID,
	REQUEST_NK,
	PAGE_TITLE,
	PAGE_DESCR,
	PAGE_KEYWORDS
	FROM DIM_REQUEST_V_ACT
) TRG ON CLS.REQUEST_NK = TRG.REQUEST_NK
WHERE TRG.REQUEST_NK IS NULL -- no such record in data mart

Aggiornamento degli attributi SCD2

/* Load request table SCD from master data */
INSERT INTO DIM_REQUEST (DIM_REQUEST_ID_HIST, REQUEST_NK, PAGE_TITLE, PAGE_DESCR, PAGE_KEYWORDS, DELETE_FLAG, UPDATE_DT)
WITH CLS  AS ( -- prepare keys
	SELECT
	'/' || NAME AS REQUEST_NK,
	TITLE       AS PAGE_TITLE,
	CASE WHEN DESCRIPTION = '' OR DESCRIPTION IS NULL
	     THEN 'n.a.' ELSE DESCRIPTION
	END AS PAGE_DESCR,
	CASE WHEN KEYWORDS = '' OR KEYWORDS IS NULL
	     THEN 'n.a.' ELSE KEYWORDS
	END AS PAGE_KEYWORDS
	FROM STG_CMS_MENU
	WHERE CONTENT_TYPE != 'folder' -- only web pages
	  AND PAGE_TITLE != 'n.a.' -- master data which make sense
)
/* updated records from stage: CLS and build reference to history: HIST */
SELECT
	HIST.DIM_REQUEST_ID AS DIM_REQUEST_ID_HIST,
	HIST.REQUEST_NK,
	CLS.PAGE_TITLE,
	CLS.PAGE_DESCR,
	CLS.PAGE_KEYWORDS,
	0 AS DELETE_FLAG,
	STRFTIME('%s','now') AS UPDATE_DT
FROM CLS,
     DIM_REQUEST_V_ACT TRG,
     DIM_REQUEST HIST
WHERE CLS.REQUEST_NK = TRG.REQUEST_NK
  AND TRG.DIM_REQUEST_ID = HIST.DIM_REQUEST_ID
  AND ( CLS.PAGE_TITLE != HIST.PAGE_TITLE /* changes only */
     OR CLS.PAGE_DESCR != HIST.PAGE_DESCR
     OR CLS.PAGE_KEYWORDS != HIST.PAGE_KEYWORDS )

Righe eliminate SCD2

/* Load request table SCD from master data */
INSERT INTO DIM_REQUEST (DIM_REQUEST_ID_HIST, REQUEST_NK, PAGE_TITLE, PAGE_DESCR, PAGE_KEYWORDS, DELETE_FLAG, UPDATE_DT)
WITH CLS  AS ( -- prepare keys
	SELECT
	'/' || NAME AS REQUEST_NK,
	TITLE       AS PAGE_TITLE
	FROM STG_CMS_MENU
	WHERE CONTENT_TYPE != 'folder' -- only web pages
	  AND PAGE_TITLE != 'n.a.' -- master data which make sense
)
/*  deleted records in data mart: TRG */
SELECT
	TRG.DIM_REQUEST_ID AS DIM_REQUEST_ID_HIST,
	TRG.REQUEST_NK,
	TRG.PAGE_TITLE,
	TRG.PAGE_DESCR,
	TRG.PAGE_KEYWORDS,
	1 AS DELETE_FLAG,
	STRFTIME('%s','now') AS UPDATE_DT
FROM (
	SELECT
	DIM_REQUEST_ID,
	REQUEST_NK,
	PAGE_TITLE,
	PAGE_DESCR,
	PAGE_KEYWORDS
	FROM DIM_REQUEST_V_ACT
	WHERE PAGE_TITLE != 'n.a.' -- track master data only
	  AND DELETE_FLAG = 0 -- not already deleted
) TRG
LEFT OUTER JOIN CLS ON TRG.REQUEST_NK = CLS.REQUEST_NK
WHERE CLS.REQUEST_NK IS NULL -- no such record in stage

Ogni fonte di dati deve essere accompagnata da una descrizione formale, ad esempio, in un file readme.txt:

Destinatario dei dati formalmente/tecnicamente: nome, indirizzo email
Fornitore dei dati formalmente/tecnicamente: nome, indirizzo email
Fonte dei dati: percorso del file, nomi dei servizi
Informazioni di accesso ai dati: utenti e password

Lo schema di movimento dei dati aiuterà nel processo di manutenzione e aggiornamento, ad esempio in forma testuale:

Spostamento del file. Fonte: ftp.domain.net: /logs/access.log Obiettivo: /var/www/access.log
Lettura in stage. Obiettivo: STG_ACCESS_LOG
Caricamento e trasformazione. Obiettivo: FCT_ACCESS_REQUEST_REF_HH
Caricamento e trasformazione. Obiettivo: FCT_ACCESS_USER_AGENT_DD
Rapporto. Obiettivo: /var/www/report.html

Risultato

Così, l'articolo descrive meccanismi come l'integrazione dei dati di base e l'introduzione di nuovi livelli di aggregazione. Sono necessari per la costruzione di data warehouse con l'obiettivo di ottenere ulteriori conoscenze e migliorare la qualità delle informazioni.

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, server VPS VDS 🔥 Acquista hosting affidabile per siti web con protezione DDoS, server VPS VDS | ProHoster