Új hozzászólás Aktív témák
-
modder
aktív tag
válasz pittbaba #1594 üzenetére
érdekes probléma, és ebből nem tudjuk meg, hogy miért lassú.
Azt mondod gps koordináták alapján akarod kiszedni, hogy melyik megállóban áll. Be tudnád írni a pontos lekérdezést, és egy-egy sor példát a három táblából? Feltételezemm, hogy a telefon nem pont ugyanazt a gps koordinátát fogja visszaadni, amit a táblában tárolsz, tehát ilyen kisebb-nagyobb összehasonlításokat végzel, ami elég költséges lehet.
Plusz nem értem, hogy miért nehéz bármit is változtatni az eredeti formátumon. Gondolom úgy működik, hogy az ember wifi közelben updateli az adatbázist, ekkor akármilyen transzformációt csinálhatsz rajta, majd úgy mented el az SQLite adatbázsiban, ahogy akarod. Keresésénél kell gyorsan működnie, nem updatenél
[ Szerkesztve ]
-
Sk8erPeter
nagyúr
válasz pittbaba #1596 üzenetére
látatlanban: indexelés, EXPLAIN?
Szerk.: ja, most látom, hogy írtad is (csak átfutottam a kérdéseden):
"Olvastam, hogy létre lehet hozni index-et a tábla oszlopaihoz, milyen oszlopokhoz érdemes?"
legalább próbálkozz egy EXPLAIN-nel. Na de konkrétabbat majd ha esetleg kipróbáltam (és elolvastam normálisan a kérdésedet ), meg ha addig nem érkezik másik válasz.[ Szerkesztve ]
Sk8erPeter
-
modder
aktív tag
válasz pittbaba #1596 üzenetére
kíváncsiságból én is feltettem notin mysql-be betöltöttem, és elkezdtem futtatni a lekérdezésedet. Nem tudtam végigvárni
1) Ez egy viszonylag normalizált adathalmaz, de nem feltétlenül lesz jó keresések szempontjából
2) mivel az adatbázis csak lekérdezésre lesz használva, simán megcsinálhatod, hogy létrehozol különböző táblákat, amik a keresést megkönnyítik: a relációkat denormalizálod, azaz egy adat, és az adatok közötti függőségek többszörösen lesznek letárolva. Ezzel azt nyered, hogy gyorsabban fogsz tudni keresni.
A "csak lekérdezéseket" azért emeltem ki, mert így nem kell majd azzal foglalkoznod, hogy az újonnan beszúrt adatok elrontják-e az adatbázist. Például az egyik táblába beszúrod, de a másikba elfelejted, satöbbi.3) Igen, az indexelés, amit már említettek. A megálló nevére rá kell tenned egy indexet mindenképpen, ha így keresel, viszont nem hiszem, hogy SQLiteban van fulltext index: azaz szövegen belüli indexelés. Mivel LIKE %valami%-kal keresel, mindenképpen be fogja olvasni a rekordot, belemászik a szövegbe, és rákeres a szövegrészletre, szóval hiába indexeled, semmit nem fog érni. Max akkor, ha tökéletes egyezést keresel.
Többi indexelés:
-- stops.stop_id elsődleges kulcs, állítsd be annak, vagy tegyél rá egy indexet;
-- stop_times.trip_id -ra és stop_times.stop_id -ra külön-külön tegyél egy indexet;
-- trips.trip_id -ra tegyél egy indexet
azért ezekre, mert ezek azok az oszlopok, amik mentén te joinolsz, és ezek által az id-k alapján fog keresni az adatbázis.ezekkel az indexekkel nekem a keresés 3 másodperc alatt lefutott laptopon. telefonon nem tudom milyen lesz...
Konkrétizálva:
Te most azt csinálod, hogy rákeresel a megálló nevére, majd megálló id alapján groupolod egy másik tábla oszlopa alapján, hogy ha egy utcában több megálló is van, azokat is megkapd. Ezzel még csak a megállókat találod meg, de nem nyersz információt az áthaladó trippekről. Az információ amire valójában szükséged van az a megálló_neve, megálló_id.Ehhez képest te összejoinolod mind a három táblát. tegyük fel, hogy a stops táblából megtalálja a megfelelő sorokat amik pl az Örs vezér tere-re stimmelnek, ez lesz pl 10 sor, akkor szépen elkezdi végigkeresni a másik két táblában a hozzájuk tartozó sorokat, de a trip_id és a departure_time nem fog információt hordozni, mert groupoltad az egészet stop_id alapján, szóval egy megállóhoz csak egy trip_id-t fog kiadni... szóval ez így teljesen rossz.
Ami neked kell ebben az esetben:
SELECT stop_name,stops.stop_id FROM stops WHERE stops.stop_name LIKE '%Örs%' GROUP BY stops.stop_idViszont te GPS alapján akarod megtalálni, ez is jó lesz. Indexelned kell a stop_lat és stop_lon mezőket, és lekérdezed úgy, ahogy írtad. Csak a megállót! Akkor felhasználó kiválasztja a pontos megállót, így az átmenő trip-eket már csak az alapján kell keresned (fölösleges a közelben lévő megállókon átmenő tripeket is megkeresni).
Átmenő trippek:
SELECT * FROM `stop_times` WHERE stop_times.stop_id = valami and `departure_time` > "06:00:00"Optimalizálás:
Visszatérve ahhoz, amit a legelején írtam a denormalizálásról. Nekem ezek a lekérdezések a belinkelt adathalmazon elég gyorsan lefutottak, de telefonon lehet, hogy más lesz a helyzet. Először próbáld ki rendesen indexekkel, hogy milyen eredményeket kapsz, és ha nem jók, akkor el lehet kezdeni szétdarabolni pl. a stops táblát 10 külön táblára, ezt hívják particionálásnak. Feltéve, hogy az SQLite van olyan intelligens, hogy nem olvassa be a memóriába az egész adatbázis fájlt, hanem beindexeli hogy melyik tábla hol kezdőik a fájlban, ezzel rendesen meg tudod gyorsítani a dolgokat.Például szétdarabolod a stops táblát 10 táblára a stop_name szerint egyenletes eloszlásban, alfabetikusan növekvő sorrendben. Amikor név alapján akar keresi, tudni fogod egyből, hogy melyik táblában keress, mert tudod, hogy melyik tábla mettől meddig tartalmaz stop_name elemeket. Ez ugye csak név alapján keresésnél hasznos, úgy ha a felhasználótól elvárod, hogy a begépelt megállónévnek az eleje egyezzen valamelyik megállónévvel.
A stop_times feldarabolása. Mivel ez a tábla rohadt nagy, ezzel is tudsz nyerni időt. Én a stop_id alapán darabolnám fel szintén alfabetikusan hasonlóan ahogy az előbb írtam, el tudod dönteni már a stop_id alapján, hogy melyik táblában keress.
miért stops.stop_name és stop_times.stop_id alapján darabolj, és ne pl stops.stop_lan és stop_times.departure_time alapján? Azért mert az SQLite valószínűleg BTREE indexelést alkalmaz, ami nagyon jó intervallum keresésre. Alkalmazható számon, dátumon, talán még szövegen is! Viszont nem találtam , hogy lenne SQLiteban hash indexelés, ami arra jó, ha szeretnél megtalálni egy elemet konkrét értékkel. Ilyen az, amikor id-k alapján joinolsz. Amikor meg akarod keresni az adott stop_id-n áthaladó járatokat a stop_times táblában adott időponton belül, akkor megkönnyíted az adatbáziskezelő dolgát azzal, ha a particionálással 200e sor helyett csak 20e-ben kell keresnie.
Persze ez csak elmélet. az egész attól is függ, hogy a stop_times táblában először intervallumkeresést hajt végre az időpontra, és utána választja ki stop_id alapján a sorokat, vagy fordítva, de ezt már nem tudom, ki kell próbálni.
Azért jó lehetőség ez az adathalmaz optimalizálásra, mert nincsenek komplikált lekérdezések, csak egy-két féle, így ki lehet alakítani úgy a struktúrát, hogy ezeknek teljesen megfeleljen. Még ami eszembe jutott, hogy az adatbázisok általában elsődleges kulcs szerint teszik sorrendbe az adatokat fizikailag. Szóval ha a stop_times táblában (stop_id, trip_id) -t adsz meg elsődleges kulcsnak ebben a sorrendben, akkor megegyszerűsítheted az adatbáziskezelő dolgát, amikor stop_id alapján keresel, mert az ugyanahhoz a stop_id-hoz tartozó rekordok egymás mögött lesznek elhelyezkede, tehát szekvenciálisan gyorsan ki tudja olvasni az összeset.
De amúgy az is lehet, hogy simán az indexekkel tökéletesen gyorsan fog működni telefonon is, és az egész novella, amit leírtam teljesen fölösleges
-
modder
aktív tag
válasz pittbaba #1606 üzenetére
Értem, igazad van. Ezt már nincs kedvem végiggondolni, hogy pontosan hogyan lenne érdemes megcsinálni a kereséseket úgy, hogy a legközelebbi olyan megállót adja meg, ahol adott járat szám megáll, de szerintem adtam ötleteket. A lényeg, hogy mindig jól gondold végig, hogy mi kell, és fölöslegesen ne joinolj táblákat, fölösleges infot ne tegyél bele a selectbe.
Ja, az indexelést se állítsd be minden oszlopra, hátha kell alapon, mert az plusz tárhely, és nem fog mindig gyorsulást okozni a lekérdezésekben.A tábladarabolással kicsit elszaladt velem a ló, csak akkor kezdj bele, ha látod, hogy egyébként lassúak a lekérdezéseid. Szívesen!
-
martonx
veterán
válasz pittbaba #1606 üzenetére
Én is belebeszélhetek? Koncepcionálisan hibáztál.
Ne pöcsölj SQLite-al, egyszerűen nem erre való. Az egész DB-t told fel valahova a felhőbe, tegyél rá egy webszolgáltatást, vagy web api-t, és az android-os alkalmazásod meg hívogassa azon keresztül. Most komolyan te egy 600-1000 mhz-s kis fos telefon procitól várod el, hogy többszázezer soros, join-olt SQLite db-ből találjon meg bármit is pillanatok alatt? Indexelheted ezt akárhogy, akkor is megfőzöl egy kávét, amíg szegény kis proci végignyálazza akár csak az indexeket.Én kérek elnézést!
-
modder
aktív tag
válasz pittbaba #1611 üzenetére
ha csak egy szimpla szelektet csinálsz a stop_times táblában pl az időpontra vagy a stop_id-ra vonatkozóan az is lassú? Miután beállítottad az indexelést, újra betöltötted az adatokat a táblába? Azért járj utána egy kicsit hogyan működik az SQLite, ha nem töltötted be újra az adatokat, lehet nem is építette föl az indexet.
-
modder
aktív tag
válasz pittbaba #1615 üzenetére
hát az, hogy a csv-t szépen betöltötted az adatbázisba korábban. Utána ahogy ajánlottuk rátettél a különféle mezőkre indexeket. Ez gyorsított valamit a dolgon? Arra akarok kilyukadni, hogy lehet nem fogja indexelni a már bent lévő adatokat, hanem ki kell ürítened a táblákat és újra betöltened ahhoz, hogy szépen felépítse az indexeket.
De ez csak egy erős tipp, egyáltalán nem értek az SQLitehoz
[ Szerkesztve ]
-
pittbaba
aktív tag
válasz pittbaba #1622 üzenetére
Megvan db név után tábla névvel kell paraméterezni a mysqldump parancsot.
Kíváncsi vagyok így már megeszi e.
Amit próbálok php-ból, megosztom, hátha segít, vagy kiderül hogy rossz ( most kb 40 perc míg feltöltődik az új sql fájl, addig nem tudom tesztelni )$query = file_get_contents("filename.sql");
$ret = mysql_query($query) or die(mysql_error());PH Konfigom: Gigabyte GA-H97M-D3H, i7 4790K,GTX 960, Seasonic SS-620GM
-
modder
aktív tag
válasz pittbaba #1620 üzenetére
miért nem jó az otthoni lomhább szerveren sebességet tesztelni? gondolom nem egy 600Mhz-ces intel pentium III-ad van
A phpmyadminnak van olyan lehetősége, hogy bemásolsz egy fájlt az egyik könyvtárába a szerveren, és onnan veszi fel, így feltöltheted FTP-n a megfelelő könyvtárba, majd importnál kiválasztod a webes felületen. Azért még így is gondot fog okozni a valószínűleg 30 másodperces default php max execution time.
Egyébként nem kell konvertálni csv-ből sql-re, csv-t is tud importálni, és azt lehet, hogy könnyebben szétdarabolod egy egyszerű szkripttel.
Persze ha localhoston tesztelnél, akkor kényed-kedvedre állíthatnál a php exec timeon, és egyszerűbben bemásolhatnád a fájlt a phpmyadmin megfelelő könyvtárába. Felteszel egy Easy PHP-t, abban alapból van phpmyadmin, mysql szerver is, működik out of the box.
Ha tényleg nem egy tízéves az "otthoni lomhább gép", én inkább azon próbálkoznék, nem kell ehhez egy über szerver.
-
Sk8erPeter
nagyúr
válasz pittbaba #1622 üzenetére
Elolvastad a leírását annak, amit linkeltem? A hsz.-edből nem úgy tűnt.
Azt sem értem, miért feltételezed, hogy na majd a következő hsz.-edben írt scripted megoldja, ami csak annyit csinál, hogy egy az egyben beolvassa az egész dumpot, és megpróbálja lefuttatni a query-t. Miért feltételezed, hogy ennél majd nem ütközöl ugyanazokba a korlátokba?
[ Szerkesztve ]
Sk8erPeter
-
őstag
válasz pittbaba #1623 üzenetére
Ez az én sufni-tuning megoldásom. Otthoni 4 éves gépen 114 mp., szerveren 46 mp. alatt töltötte be mysql-be a 112 mbyte-os fájlt. Indexeket nem állítottam be, mert úgy nagyon lassú volt.
<?php
$sorinsert=10000; // ennyi soronként insert mysql-be
$szerver='127.0.0.1';
$user='gtfsuser';
$pass='';
$adatbazis='gtfs';
$tabla='stop_times';
$file='stop_times.txt';
// kapcsolódás
if ( !mysql_connect($szerver, $user, $pass) ) { echo 'Nem érhetõ el a szerver.'; die(); }
if ( !mysql_select_db($adatbazis) ) { echo 'Nem érhetõ el a '.$adatbazis.' adatbázis.'; die(); }
mysql_query('TRUNCATE TABLE `stop_times`');
mysql_query('FLUSH TABLE `stop_times`');
$query=''; $ido=idopont();
// file betöltés
if ( !$fa=fopen($file, 'r') ) { echo 'Nem nyitható meg: '.$file; die(); }
$sor=fgets($fa, 256); $sorszam=0; // elsõ sor kihagyása
while ( !feof($fa) ) {
@set_time_limit(30);
$sor=fgets($fa, 256);
$sorszam++;
$sor=str_replace(",", "','", $sor);
if ( $query<>'' ) { $query.=', '; }
$query.=" ('".$sor."', '')";
if ( $sorszam==$sorinsert ) {
mysql_query('INSERT INTO '.$tabla.' VALUES '.$query);
echo $sorinsert.' sor beillesztve<br>';
$sorszam=0; $query='';
}
}
if ( $query<>'' ) { mysql_query('INSERT INTO '.$tabla.' VALUES '.$query); }
fclose($fa);
echo '<br>Eltelt idõ: '.idopont($ido);
// eltelt idõ
function idopont($t=0) {
list( $usec, $sec ) = explode(" ",microtime());
$ido=( (float)$usec+(float)$sec );
if ( $t===0 ) { return $ido; }
$s=(float)$ido-$t;
$s=round($s, 4);
return $s;
}
/*
CREATE TABLE IF NOT EXISTS `stop_times` (
`trip_id` varchar(20) COLLATE utf8_hungarian_ci NOT NULL,
`arrival_time` varchar(8) COLLATE utf8_hungarian_ci NOT NULL,
`departure_time` varchar(8) COLLATE utf8_hungarian_ci NOT NULL,
`stop_id` varchar(20) COLLATE utf8_hungarian_ci NOT NULL,
`stop_sequence` varchar(20) COLLATE utf8_hungarian_ci NOT NULL,
`shape_dist_traveled` varchar(20) COLLATE utf8_hungarian_ci NOT NULL,
`kulcs` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`kulcs`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_hungarian_ci;
*/
?> -
Sk8erPeter
nagyúr
válasz pittbaba #1656 üzenetére
Javaslat: [link]
http://stackoverflow.com/questions/924265/what-does-the-key-keyword-mean
http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html
http://stackoverflow.com/questions/1401572/what-are-differences-between-index-v-s-key-in-mysql
http://www.quora.com/MySQL/What-is-the-difference-between-using-KEY-and-INDEX-in-MySQL
http://stackoverflow.com/questions/1071180/is-the-primary-key-automatically-indexed-in-mysql
http://www.quora.com/MySQL/What-is-the-difference-between-using-KEY-and-INDEX-in-MySQLAz a baj, hogy túl kevés az információ a zzzinterneten...
Sk8erPeter
-
Sk8erPeter
nagyúr
válasz pittbaba #1661 üzenetére
De nézd meg az eredeti kérdésedet, abból nem az derül ki, hogy megpróbáltál volna minimális kutatómunkát is végezni kérdés előtt. Most érted, tök más, ha úgy kérdezed, hogy ezt meg azt találtam, és az alapján így meg úgy értelmezem, szerintetek így van-e, vagy ha tényleg nem találsz valamit, akkor megírod, hogy nem sikerült erről normális infót találnod, mintha egyszerűen rábízod másra az elméleti fejtegetést, vagy a találatok belinkelését (ahogy én is tettem, segítőszándékkal), hadd töltsön csak vele időt más helyetted... Ezáltal vész el a dolog szakmaisága, mert onnantól kezdve nem egy dolog jobb/rosszabb megvalósíthatóságáról, lehetőségekről, ötletekről beszélgetünk, hanem szimplán olyan dologról, ami a dokumentációban is kicsi keresgélés alapján megtalálható. Az eredeti kérdésedben ezzel szemben érdekes problémát vetettél fel, kaptál is választ rá bőven.
Sk8erPeter
-
Lortech
addikt
válasz pittbaba #1699 üzenetére
A NULL speciális érték, pl. Oracle-ben nullt bármihez hasonlítod = / != -vel, egyaránt unknown eredményt ad. Null helyett érdemes lehet egy speciális, nullt szimbolizáló értéket adni a mezőnek, vagy ha az nem opció, akkor mindig IS NULL / IS NOT NULL-lal (is) vizsgálni.
Thank you to god for making me an atheist
-
Szmeby
tag
válasz pittbaba #2849 üzenetére
Ilyesmire gondoltál?
select *
from hirdetes h
inner join user u on u.id = h.userid
inner join kategoria1 k1 on k1.id = h.kategoria1
inner join kategoria2 k2 on k2.id = h.kategoria2
inner join kategoria3 k3 on k3.id = h.kategoria3
inner join custom c on c.hirdetes_id = h.id
where c.mezo_neve = 'szobak_szama' and c.ertek = 3;Egyébként nem lenne ésszerűbb az egymástól független fogalmakat külön táblában tárolni?
Vagyis külön tábla az ingatlan hirdetéseknek, külön az autóknak, stb.
És akkor lehet minden szépen field. Az úgy már csak nem olyan sok. -
sztanozs
veterán
válasz pittbaba #2849 üzenetére
Szvsz, mindent vigyél fel, mint általános kategóriát valahogy így:
Hirdetés
hirdetés_id, feltöltő_id, hirdetés_típusa_id, hirdetés_címe, hirdetés_szövegHirdetés típus
hirdetés_típus_id, hirdetés_típus_szövegKategória_típus
kategória_id, hirdetés_típus_id, kategória_név, kategória_leírásHirdetés_kategória_értékek
hirdetés_id, kategória_id, értékLekérdezés
SELECT
h.hirdetés_id,
h.hirdetés_címe,
h.hirdetés_szöveg,
t.hirdetés_típus_szöveg,
k.kategória_név,
e.érték
FROM
hirdetés h
JOIN Hirdetés_kategória_értékek e ON h.hirdetés_id = e.hirdetés_id
JOIN Hirdetés típus t ON h.hirdetés_típusa_id = t.hirdetés_típusa_id
JOIN Kategória_típus k ON e.kategória_id = k.kategória_id
WHERE
h.hirdetés_id IN (
SELECT hi.hirdetés_id FROM
hirdetés hi
JOIN Hirdetés_kategória_értékek ei ON hi.hirdetés_id = ei.hirdetés_id
JOIN Kategória_típus ki ON ei.kategória_id = ki.kategória_id
WHERE
ki.kategória_név = "Szobák száma" AND ei.érték = 3
)[ Szerkesztve ]
JOGI NYILATKOZAT: A bejegyzéseim és hozzászólásaim a személyes véleményemet tükrözik; ezek nem tekinthetők a munkáltatóm hivatalos állásfoglalásának...
-
Szmeby
tag
válasz pittbaba #2851 üzenetére
Tele van inner joinnal. Rendesen indexelt táblákkal nincs ebben semmi kíméletlen.
Az adatbázistól elkérheted egy lekérdezés execution plan-jét (legalábbis Oracle alatt biztosan), abból ki lehet bogarászni, hogy hogyan optimalizálja azt, és hol lehet gyorsítani rajta.Természetesen ha nem használod pl. a kategória3-mat, nem kell belevenni a lekérdezésbe. Továbbá biztosan nem lesz szükséged az összes tábla összes mezőjére, így a select * helyett a szükséges mezőnevek felsorolása célszerű.
Az ember mindig elszúrja valahol, ez természetes dolog. Azért gyakorlunk, hogy minimalizáljuk ezt.
Egy normális adatbázis több tíz, száz, ezer táblát tartalmaz - sémákba rendezve -, mindegyiknek megvan a célja. Egyes táblák akár sokszáz oszloppal rendelkezhetnek, bennük több milliárd rekorddal. Ha ezen táblák tartalmát egy táblába gyűjtenénk az adatbázis szerintem már az indexelésnél összeomlana.Viszont ezzel, hogy mindent "belehánysz" egy táblába, azt éred el, hogy borzasztóan sok _felesleges_ adattal duzzasztod azt fel. Szerencsétlen adatbázis minden teszemazt ingatlanos lekérdezésnél kénytelen végigfutni az autós meg az összes többi irreleváns hirdetések adatain/indexein is. Egy kicsit is tágabb szűrést adsz meg véletlenül, és csodálkozol, hogy miért lett ez ilyen tetü lassú.
Én úgy vélem, hogy ne hagyjuk az adatbázist feleslegesen dolgozni, ha van más lehetőség. Nagyon könnyen teljesítmény problémákba futhatsz bele, és azokon már nehezebb javítani, mint pár elrontott lekérdezésen. -
tm5
tag
válasz pittbaba #2907 üzenetére
Bár látom, hogy ez egy régi feladvány, de mivel nem láttam rá megoldást azért így utólag csak javasolnék valamit:
Szóval minden ami a apro_category_customs-ből jönne azt 1 subquery-be menne amire rékerülne egy PIVOT.
Ez egy Oracle-s példa rá.Ennek illene sokkal gyorsabbnak lennie és a query is szebb lenne.
Új hozzászólás Aktív témák
- Óra topik
- Milyen NAS-t vegyek?
- Bugok, problémák a PROHARDVER lapcsaládon
- Azonnali mobilos kérdések órája
- Súlyos adatvédelmi botrányba kerülhet a ChatGPT az EU-ban
- Milyen okostelefont vegyek?
- Milyen egeret válasszak?
- Microsoft Excel topic
- BestBuy topik
- Kerékpárosok, bringások ide!
- További aktív témák...