Kapcsolt táblák mutatózása? (INDEXES in JOIN)
Alapvető, de nem sikerült választ találnom: hogyan egyeztessek össze két követelményt?
1. Ne legyenek fölösen ismétlődő adatok - ki kell vinni őket egy újabb táblába.
2. Meglegyenek a hatékonysághoz kellő mutatók [INDEX] a lekérdezéshez használt táblában.
Látogató-kimutatás (részlete).
HA: hálóazonosító [IP]
OKULCS: országkulcs (a GeoIP alapján)
TKULCS: területkulcs (a GeoIP alapján)A látogatóról készül egy bejegyzés a "látogató" táblába. Amíg 24 órán belül újra kattintgat, csak az adott sor KATT oszlopa értékét növelem. Minden egyes kattintásával készül azonban egy-egy új sor a "látogató_lap" táblába is.
A két fentebbi lekérdezés eddig rendben is van, mert működnek a "látogató" és "látogató_lap" táblák mutatói [INDEX].
Viszont:
1. Egy látogató átlag 4× kattint. 4 sor a "látogató_lap" táblában - UGYANAZON FÖLDRAJZI ADATOKKAL.
2. +1 további sor is lesz a "látogató" táblában - UGYANAZON FÖLDRAJZI ADATOKKAL.
A fölösleges adatismétlés követelményének azzal tehetnék legszebben eleget, ha mindkét látogatótáblából eltüntetném mind a hálóazonosítót, mind az összes földrajzi adatot. Helyettük mindkettő tábla adott sorai kapnának egy (ugyanolyan) véletlenszám látogatás-azonosítót, s ezzel az azonosítóval készülne EGYETLEN sor egy külön táblában (mondjuk "látogatás"), mely tartalmazza eme adatokat. A lekérdezésben fűzéssel [JOIN] kapnám meg őket. (Vagy, ésszerűbben: csak a "látogató"-ban hagynám meg eme adatokat, s onnan fűzném a "látogató_lap"-hoz.)
Itt jön, amit nem értek. A jelen felállásban a mutatóim megfelelőek. De ha kiviszem az országkulcsot, városnevet, stb. az új "látogatás" táblába, akkor hogyan tudok ehhez mutatókat készíteni a "látogató" és "látogató_lap" táblákban? Hiszen ott nem lesznek ilyen oszlopok! Márpedig mutatók kellenek, különben akár szunyálhatok egyet, míg fut a lekérdezés.
Mivel ez alapvető(nek tűnik számomra), gondolom, a megoldás is az - csak én nem ismerem.
■ 1. Ne legyenek fölösen ismétlődő adatok - ki kell vinni őket egy újabb táblába.
2. Meglegyenek a hatékonysághoz kellő mutatók [INDEX] a lekérdezéshez használt táblában.
Látogató-kimutatás (részlete).
HA: hálóazonosító [IP]
OKULCS: országkulcs (a GeoIP alapján)
TKULCS: területkulcs (a GeoIP alapján)
SET NAMES utf8;
# ----------------------------------------------------------------
# Tábla: geoip_ország (4 oszlop)
CREATE TABLE `geoip_ország` (
`OKULCS` varchar(2) COLLATE utf8_general_ci NOT NULL COMMENT 'A GeoIP adata',
`ORSZÁG` varchar(60) COLLATE utf8_general_ci NOT NULL COMMENT 'A GeoIP adata',
`ORSZÁG_M` varchar(60) COLLATE utf8_general_ci NOT NULL COMMENT 'Magyarul',
PRIMARY KEY (`OKULCS`)
) ENGINE=MyISAM COLLATE=utf8_general_ci COMMENT='A Geoip országnevek magyarul';
# ----------------------------------------------------------------
# Tábla: geoip_terület (4 oszlop)
CREATE TABLE `geoip_terület` (
`OKULCS` varchar(2) COLLATE utf8_general_ci NOT NULL COMMENT 'A GeoIP adata',
`TKULCS` varchar(2) COLLATE utf8_general_ci NOT NULL COMMENT 'A Geoip területkulcsa',
`TERÜLET` varchar(60) COLLATE utf8_general_ci NOT NULL COMMENT 'A GeoIP adata',
`TERÜLET_M` varchar(60) COLLATE utf8_general_ci NOT NULL COMMENT 'Magyarul',
UNIQUE KEY `OKULCS` (`OKULCS`, `TKULCS`)
) ENGINE=MyISAM COLLATE=utf8_general_ci COMMENT='A Geoip területnevek magyarul';
# ----------------------------------------------------------------
# Tábla: geoip_város (4 oszlop)
CREATE TABLE `geoip_város` (
`OKULCS` varchar(2) COLLATE utf8_general_ci NOT NULL COMMENT 'A GeoIP adata',
`TKULCS` varchar(2) COLLATE utf8_general_ci NOT NULL COMMENT 'A GeoIP adata',
`VÁROS` varchar(45) COLLATE utf8_general_ci NOT NULL COMMENT 'A GeoIP adata',
`VÁROS_M` varchar(100) COLLATE utf8_general_ci NOT NULL COMMENT 'Magyarul',
UNIQUE KEY `OKULCS` (`OKULCS`, `TKULCS`, `VÁROS`)
) ENGINE=MyISAM COLLATE=utf8_general_ci COMMENT='A Geoip városnevek magyarul';
# ----------------------------------------------------------------
# Tábla: lap (4 oszlop)
CREATE TABLE `lap` (
`LAPKULCS` smallint(3) unsigned NOT NULL,
`NYELVKULCS` tinyint(1) unsigned NOT NULL default '1' COMMENT 'A lap nyelvkulcsa',
`SZÉPNÉV` varchar(20) COLLATE utf8_general_ci NOT NULL COMMENT 'A lap szép neve',
`LAP` varchar(60) COLLATE utf8_general_ci NOT NULL COMMENT 'Útvonal a főkönyvtárból kiindulva',
UNIQUE KEY `LAPKULCS` (`LAPKULCS`, `NYELVKULCS`),
KEY `LAP` (`LAP`)
) ENGINE=MyISAM COLLATE=utf8_general_ci COMMENT='A honlap lapjainak kulcsa és állománya';
# ----------------------------------------------------------------
# Tábla: nyelv (3 oszlop)
CREATE TABLE `nyelv` (
`NYELVKULCS` tinyint(1) unsigned NOT NULL auto_increment COMMENT 'A nyelv kulcsa',
`NYELV` varchar(10) COLLATE utf8_general_ci NOT NULL COMMENT 'A nyelv neve',
`NYELVKULCS2` varchar(2) COLLATE utf8_general_ci NOT NULL COMMENT 'Kétbetűs nemzetközi, a fejléchez',
PRIMARY KEY (`NYELVKULCS`)
) ENGINE=MyISAM COLLATE=utf8_general_ci COMMENT='A honlap lapjainak nyelvei' AUTO_INCREMENT=8;
# ----------------------------------------------------------------
# Tábla: látogató (8 oszlop)
CREATE TABLE `látogató` (
`IDŐ` datetime NOT NULL,
`HA` varchar(60) COLLATE utf8_general_ci NOT NULL COMMENT 'hálóazonosító',
`KATT` tinyint(3) unsigned NOT NULL default '1' COMMENT 'A 24 órán belüli letöltések száma',
`OKULCS` varchar(2) COLLATE utf8_general_ci NOT NULL COMMENT 'A GeoIP adata',
`TKULCS` varchar(2) COLLATE utf8_general_ci NOT NULL COMMENT 'A GeoIP adata',
`VÁROS` varchar(45) COLLATE utf8_general_ci NOT NULL COMMENT 'A GeoIP adata',
`SZÉLESSÉG` decimal(10,5) NOT NULL default '0.00000' COMMENT 'A GeoIP adata',
`HOSSZÚSÁG` decimal(10,5) NOT NULL default '0.00000' COMMENT 'A GeoIP adata',
KEY `IDŐ` (`IDŐ`),
KEY `ALKALOM` (`ALKALOM`),
KEY `OKULCS` (`OKULCS`, `TKULCS`, `VÁROS`),
KEY `TKULCS` (`TKULCS`),
KEY `VÁROS` (`VÁROS`)
) ENGINE=MyISAM COLLATE=utf8_general_ci COMMENT='Egy látogató, 24 órán belüli kattintgatásokkal';
# ----------------------------------------------------------------
# Tábla: látogató_lap (9 oszlop)
CREATE TABLE `látogató_lap` (
`IDŐ` datetime NOT NULL,
`HA` varchar(60) COLLATE utf8_general_ci NOT NULL COMMENT 'hálóazonosító',
`LAPKULCS` smallint(3) unsigned NOT NULL COMMENT 'A lekért lap kulcsa',
`NYELVKULCS` tinyint(1) unsigned NOT NULL COMMENT 'A nézett lap nyelvkulcsa',
`OKULCS` varchar(2) COLLATE utf8_general_ci NOT NULL COMMENT 'A GeoIP adata',
`TKULCS` varchar(2) COLLATE utf8_general_ci NOT NULL COMMENT 'A GeoIP adata',
`VÁROS` varchar(45) COLLATE utf8_general_ci NOT NULL COMMENT 'A GeoIP adata',
`SZÉLESSÉG` decimal(10,5) NOT NULL default '0.00000' COMMENT 'A GeoIP adata',
`HOSSZÚSÁG` decimal(10,5) NOT NULL default '0.00000' COMMENT 'A GeoIP adata',
KEY `IDŐ` (`IDŐ`),
KEY `LAPKULCS` (`LAPKULCS`, `NYELVKULCS`),
KEY `NYELVKULCS` (`NYELVKULCS`),
KEY `OKULCS` (`OKULCS`, `TKULCS`, `VÁROS`),
KEY `TKULCS` (`TKULCS`),
KEY `VÁROS` (`VÁROS`)
) ENGINE=MyISAM COLLATE=utf8_general_ci COMMENT='Egy kattintás, lap- és nyelvadatokkal';
# ----------------------------------------------------------------
SELECT COUNT(látogató.*) AS LÁTOGATÓ,
SUM(látogató.KATT) AS KATT,
látogató.VÁROS AS VÁROS,
geoip_város.VÁROS_M AS VÁROS_M
FROM látogató
LEFT JOIN geoip_város USING (OKULCS, TKULCS, VÁROS)
GROUP BY VÁROS
ORDER BY KATT DESC, VÁROS_M
SELECT COUNT(látogató_lap.*) AS KATT,
CONCAT(
látogató_lap.LAPKULCS,
látogató_lap.NYELVKULCS
) AS LAPAZONOSÍTÓ,
lap.SZÉPNÉV AS SZÉPNÉV,
nyelv.NYELV AS NYELV
FROM látogató_lap
LEFT JOIN lap USING (LAPKULCS)
LEFT JOIN nyelv USING (NYELVKULCS)
GROUP BY LAPAZONOSÍTÓ
ORDER BY KATT DESC, SZÉPNÉV
A két fentebbi lekérdezés eddig rendben is van, mert működnek a "látogató" és "látogató_lap" táblák mutatói [INDEX].
Viszont:
1. Egy látogató átlag 4× kattint. 4 sor a "látogató_lap" táblában - UGYANAZON FÖLDRAJZI ADATOKKAL.
2. +1 további sor is lesz a "látogató" táblában - UGYANAZON FÖLDRAJZI ADATOKKAL.
A fölösleges adatismétlés követelményének azzal tehetnék legszebben eleget, ha mindkét látogatótáblából eltüntetném mind a hálóazonosítót, mind az összes földrajzi adatot. Helyettük mindkettő tábla adott sorai kapnának egy (ugyanolyan) véletlenszám látogatás-azonosítót, s ezzel az azonosítóval készülne EGYETLEN sor egy külön táblában (mondjuk "látogatás"), mely tartalmazza eme adatokat. A lekérdezésben fűzéssel [JOIN] kapnám meg őket. (Vagy, ésszerűbben: csak a "látogató"-ban hagynám meg eme adatokat, s onnan fűzném a "látogató_lap"-hoz.)
Itt jön, amit nem értek. A jelen felállásban a mutatóim megfelelőek. De ha kiviszem az országkulcsot, városnevet, stb. az új "látogatás" táblába, akkor hogyan tudok ehhez mutatókat készíteni a "látogató" és "látogató_lap" táblákban? Hiszen ott nem lesznek ilyen oszlopok! Márpedig mutatók kellenek, különben akár szunyálhatok egyet, míg fut a lekérdezés.
Mivel ez alapvető(nek tűnik számomra), gondolom, a megoldás is az - csak én nem ismerem.
Denormalizáció
Idézet a Microsoft normalizálásáról szóló cikkből:
Jó hír - ezek szerint még sem
Másrészt kár, hogy nincs megoldás. Így kb. 3-szorosa az adattár mérete annak, amit el szerettem volna érni. Évi 20-30 MB a kimutatás szükséglete, ezt gondoltam leszorítani 10-re.
csatlakozom
off: (oktató intézményekhez):
Köszönöm a válaszokat