Më shumë statistika për saitin në magazinën e tij të vogël

Duke analizuar statistikën e faqes, ne marrim një pasqyrë të asaj që ndodh me të. Ne përputhim rezultatet me njohuritë e tjera mbi produktin ose shërbimin dhe kështu përmirësojmë përvojën tonë.

Kur përfundon analiza e rezultateve të para, pasqyrohet informacioni dhe bëhen përfundime, fillon faza e ardhshme. Lindin ide: çfarë do të ndodhte nëse do ta shikonim të dhënat nga një këndvështrim tjetër?

Në këtë fazë ka kufizime në mjetet e analizës. Kjo është një nga arsyet pse mjetin Google Analytics nuk e kam gjetur të mjaftueshëm, për shkak të mundësive të kufizuara për të parë dhe manipuluar të dhënat e mia.

Gjithmonë kam dëshiruar të ngarkoj shpejt të dhënat bazë (master-data), të shtoj një nivel tjetër aggregimi ose të interpretoj ndryshe vlerat ekzistuese.

Kjo është e lehtë për t'u bërë në depën e vogël që kam në bazë të skedarit access.log dhe për këtë mjafton gjuha SQL.

Pra, cilat pyetje doja të gjeja përgjigje?

ÇfarĂ« dhe kur Ă«shtĂ« ndryshuar nĂ« faqen e internetit

Historiku i ndryshimeve të të dhënave bazë (master-data) gjithmonë ka interes.

Më shumë statistika për saitin në magazinën e tij të vogël

Kërkesa SQL e raportit

SELECT
	1 as 'SideStackedBar: Përditësimet e Përmbajtjes sipas Muajve',
	strftime('%m/%Y', datetime(UPDATE_DT, 'unixepoch')) AS 'Dita',
	COUNT(CASE WHEN PAGE_TITLE != 'n.a.' THEN DIM_REQUEST_ID END) AS 'Përditësimet e faqeve të internetit',
	COUNT(CASE WHEN PAGE_DESCR = 'IMAGES' THEN DIM_REQUEST_ID END) AS 'Ngarkimet e Imazheve',
	COUNT(CASE WHEN PAGE_DESCR = 'VIDEO' THEN DIM_REQUEST_ID END) AS 'Ngarkimet e Videove',
	COUNT(CASE WHEN PAGE_DESCR = 'AUDIO' THEN DIM_REQUEST_ID END) AS 'Ngarkimet e Audios'
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

Për shembull, në një moment të caktuar u bë optimizimi për motorët e kërkimit ose u shtua përmbajtje e re në faqen e internetit, prandaj pritet një rritje e trafikut.

Grupet e përdoruesve

Shembulli më i thjeshtë i një grupi mund të jetë agjenti i përdoruesit ose emri i sistemit operativ.

Matja e agjentëve të përdoruesve ka grumbulluar rreth një mijë regjistrime dhe më interesonte të shihja dinamikën e shpërndarjes së agjentëve brenda grupit.

Më shumë statistika për saitin në magazinën e tij të vogël

Kërkesa SQL e raportit

SELECT
	1 AS 'SideStackedBar: Agjentët e Përdoruesve',
	AGENT_OS AS 'OS',
	SUM(CASE WHEN AGENT_BOT = 'n.a.' THEN 1 ELSE 0 END ) AS 'Agjenti i Përdoruesve',
	SUM(CASE WHEN AGENT_BOT != 'n.a.' THEN 1 ELSE 0 END ) AS 'Agjenti i Bots'
FROM DIM_USER_AGENT
WHERE DIM_USER_AGENT_ID != -1
GROUP BY AGENT_OS
ORDER BY 3 DESC

Më shumë kombinime të ndryshme agjentësh vijnë në faqen e internetit nga bota e Windows. Në mesin e të paqenësuarve ishin ato si WhatsApp, PocketImageCache, PlayStation, SmartTV etj.

Aktiviteti i grupeve të përdoruesve sipas javëve

Duke bashkuar disa grupe, mund të vëzhgosh shpërndarjen e aktivitetit të tyre.

Përdoruesit e grupeve të Linux konsumojnë më shumë trafik në sit sesa të gjitha grupet e tjera.

Më shumë statistika për saitin në magazinën e tij të vogël

Kërkesa SQL e raportit

SELECT
1 as 'StackedBar: Sasia e Trafikut nga OS-ja e Përdoruesit dhe nga Java',
strftime('%W java', datetime(FCT.EVENT_DT, 'unixepoch')) AS 'Java',
SUM(CASE WHEN USG.AGENT_OS IN ('Android', 'Linux') THEN FCT.BYTES ELSE 0 END)/1000 AS 'Përdoruesit Android/Linux',
SUM(CASE WHEN USG.AGENT_OS IN ('Windows') THEN FCT.BYTES ELSE 0 END)/1000 AS 'Përdoruesit Windows',
SUM(CASE WHEN USG.AGENT_OS IN ('Macintosh', 'iOS') THEN FCT.BYTES ELSE 0 END)/1000 AS 'Përdoruesit Mac/iOS',
SUM(CASE WHEN USG.AGENT_OS IN ('n.a.', 'BlackBerry') THEN FCT.BYTES ELSE 0 END)/1000 AS 'Të Tjerë'
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.' /* përdoruesit vetëm */
  AND HST.STATUS_GROUP IN ('Të Sukesshme') /* faqe të mira */
  AND datetime(FCT.EVENT_DT, 'unixepoch') > date('now', '-3 muaj')
GROUP BY strftime('%W java', datetime(FCT.EVENT_DT, 'unixepoch'))
ORDER BY FCT.EVENT_DT

Konsumim intensiv i trafikut

Nga tabela janë dukshme grupet më aktive të përdoruesve dhe dita e aktivitetit të tyre.
Grupet më aktive i përkasin klasterit Linux.

Më shumë statistika për saitin në magazinën e tij të vogël

Kërkesa SQL e raportit

SELECT
1 AS 'Tabela: Agjenti i Përdoruesit me Përdorim të Lartë',
strftime('%d.%m.%Y', datetime(FCT.EVENT_DT, 'unixepoch')) AS 'Dita',
ROUND(1.0*SUM(FCT.BYTES)/1000000, 1) AS 'Trafiku MB',
ROUND(1.0*SUM(FCT.IP_CNT)/SUM(1), 1) AS 'IP-të',
ROUND(1.0*SUM(FCT.REQUEST_CNT)/SUM(1), 1) AS 'Kërkesat',
USA.DIM_USER_AGENT_ID AS 'ID',
MAX(USA.USER_AGENT_NK) AS 'Agjenti i Përdoruesit',
MAX(USA.AGENT_BOT) AS 'Bot'
FROM
FCT_ACCESS_USER_AGENT_DD FCT,
DIM_USER_AGENT USA
WHERE FCT.DIM_USER_AGENT_ID = USA.DIM_USER_AGENT_ID
  AND datetime(FCT.EVENT_DT, 'unixepoch') >= date('now', '-30 ditë')
GROUP BY USA.DIM_USER_AGENT_ID, strftime('%d.%m.%Y', datetime(FCT.EVENT_DT, 'unixepoch')) 
ORDER BY SUM(FCT.BYTES) DESC, FCT.EVENT_DT
LIMIT 10

Duke përdorur atributet e ditës dhe ID-së së agjentit, krijohet mundësia për të gjetur dhe ndjekur shpejt statistikën ditore të grupeve të veçanta të përdoruesve. Në rast nevoje, mund të gjendet shpejt informacioni i detajuar në tabelën e skenës.

Si të merrni informacion?

Informacioni nga skedari access.log mund të bëhet edhe më efektiv nëse integrohen burime të tjera të dhënash, duke futur nivele të reja agregimi dhe grupimi.

Të dhënat dhe entitetet themelore

TĂ« dhĂ«nat themelore pĂ«rfshijnĂ« informacionin mbi entitetet: faqe web-i, imazhe, pĂ«rmbajtje video dhe audio, nĂ« rastin e dyqanit — produkte.

Entitetet vetë shërbejnë si masa, dhe procesi i ruajtjes së ndryshimeve të atributit quhet historizim. Në një bazë të dhënash ky proces shpesh realizohet në formën e masave që ndryshojnë ngadalë (SCD).

Burimi i të dhënave themelore mund të jetë një sërë sistemesh të ndryshme, prandaj në shumicën e rasteve duhet të integrohen.

Masa që ndryshon ngadalë

Masa DIM_REQUEST do të përmbajë informacion mbi kërkesat në sit në formën historike.

Tabela SCD2

KRIJO TABELË DIM_REQUEST ( 
  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.', 
  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);

Përveç tij, do të krijojmë një pamje që tregon gjithmonë të gjitha regjistrimet në gjendjen e fundit. Nevojitet për ngarkimin e vetë matjes.

Më shumë statistika për saitin në magazinën e tij të vogël

Pamja aktuale 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;

Dhe pamja ku për çdo regjistrim është mbledhur informacion historik. Nevojitet për ndërtimin e një lidhjeje historikisht të saktë me faktet.

Më shumë statistika për saitin në magazinën e tij të vogël

Pamja historike 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;

Agregimi i të dhënave

Kompresimi (agregimi) lejon vlerësimin e të dhënave në një nivel më të lartë dhe zbërthimin e anomalive dhe tendencave që nuk janë të dukshme në raportet e detajuara.

Për shembull, në matjen me kodet e statusit të kërkesave DIM_HTTP_STATUS do të shtojmë një grup:

STATUS / GRUP
0xx / n.a.
1xx / Informues
2xx / Sukseshëm
3xx / Riorientim
4xx / Gabim i klientit
5xx / Gabim serveri

Matja e agjentëve të përdoruesit DIM_USER_AGENT do të përmbajë atribute të AGENT_OS dhe AGENT_BOT, të cilat i përkasin grupeve. Ato mund të plotësohen gjatë procesit ETL:

Ngarkimi 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

Integrimi i të dhënave

Përfshin organizimin e transferimit të të dhënave nga sistemi operativ në raport. Për këtë, është e nevojshme të krijohet një tabelë stage me një strukturë, të ngjashme me burimin.

Informacioni mbi faqet e internetit kalon në stage nga backup-i i CMS në formën e kërkesave të futjes.

Ngarkimi i tabelës historike DIM_REQUEST me të dhëna bazike ndodh në tri hapa: ngarkimi i çelësave dhe atributeve të rinj, përditësimi i atyre ekzistuese dhe regjistrimi i regjistrimeve të fshiara.

Ngarkimi i regjistrimeve të reja 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

Përditësimi i atributeve 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 )

Regjistrimet e fshira 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

Çdo burim tĂ« dhĂ«nash duhet tĂ« shoqĂ«rohet me njĂ« pĂ«rshkrim formal, pĂ«r shembull, nĂ« njĂ« skedĂ« readme.txt:

Marrësi i të dhënave formal/teknik: emri, adresa elektronike
Furnizuesi i të dhënave formal/teknik: emri, adresa elektronike
Burimi i të dhënave: rruga e skedës, emrat e shërbimeve
Informacioni mbi qasjen në të dhëna: përdoruesit dhe fjalëkalimet

Skema e lëvizjes së të dhënave do të ndihmojë në procesin e mirëmbajtjes dhe përditësimit, për shembull, në formë tekstuale:

Shkarkimi i skedës. Burimi: ftp.domain.net: /logs/access.log Qëllimi: /var/www/access.log
Leximi në stage. Qëllimi: STG_ACCESS_LOG
Ngarkimi dhe transformimi. Qëllimi: FCT_ACCESS_REQUEST_REF_HH
Ngarkimi dhe transformimi. Qëllimi: FCT_ACCESS_USER_AGENT_DD
Raporti. Qëllimi: /var/www/report.html

Përfundimi

Kështu, artikulli përshkruan mekanizma të tillë si integrimi i të dhënave themelore dhe përfshirja e niveleve të reja të agregimit. Këto janë të nevojshme gjatë ndërtimit të magazinave të të dhënave me qëllim që të fitojmë njohuri shtesë dhe të përmirësojmë cilësinë e informacionit.

Burimi: habr.com

Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS đŸ”„ Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS | ProHoster