Enormno podatkov, sesutje serverja

Pozdravljeni mojstri!

Prvič se srečujem z zelo zelo veliko bazo podatkov v PHP/MySQL.
Imam tabelo ki im trenutno 2,571,934 zapisov. Notri je kar precej polj z veliko podatki.

Za potrebe statistike moram čez vsa ta polja spustiti:

$where = "user1Id = '".$id."' OR user2Id='".$id."' OR user3Id='".$id."' OR user4Id='".$id."'";

da najdem uporabnika in vse njegove rezultate. Baza se takoj sesuje ko to spustim skozi.
Kakšne so rešitve in alternative.. Kaj uporabiti, oz. kaj iskati pri Googlu?

Uporabljam CodeIgniter.

Hvala!

23 odgovorov

Kaj pa pomeni da se sesuje? Kakšna napaka, ali dejansko vse freezne za neskončno časa?

1

@MitjaST, to javi tole:

Array ( [0] => stdClass Object ( [id] => 1 [select_type] => SIMPLE [table] => tarok_game [type] => ALL [possible_keys] => user1Id [key] => [key_len] => [ref] => [rows] => 2595105 [Extra] => Using where ) )

@b00mbar: Freeze, potem pa memory limit hit.

Baza izgleda takole:
http://s3.amazonaws.com/awesome_screenshot/1829120?AWSAccessKeyId=0R7FMW7AXRVCYMAPTPR2&Expires=1364221522&Signature=wLZhBSDQM7fhj7Q7uzsVpe0Pw4g%3D

Torej, dva miljona in pol vrstic, vsaka vrstica ima 4 polja možnih userIdjev.. za potrebe statistike moram single userju najdit vse igre v katerih je igral. Zdej, lahko je njegov id na enem izmed teh 4 polj.

Link ne dela ok, javi AccessDenied.

Polje Key imaš prazno torej ne izbere indexa. Kopiraj še SQL, nekaj pri tem ni ok.

1

Popravek image:

Si poskusil Index na vsakem polju posebej od teh štirih?

Malo čudno je da bi ti sesulo server zaradi tega.

Če narediš kopijo kompletne baze in poženeš ta query na kopiji, se še vedno sesuje?

1

Ubistvu samo memory limit dosežem.. Index na vsakem polju pa bom probal.

zaay123:
Ubistvu samo memory limit dosežem.. Index na vsakem polju pa bom probal.

Lahko prikažeš SQL, ki ga izvedeš in zraven pripišeš kaj želiš doseči.
Sumim namreč, da napačno uporabljaš SQL poizvedbe. Mogoče selectaš preveč podatkov brez LIMIT, ali kaj podobnega.

1
$where = "user1Id = '".$id."' OR user2Id='".$id."' OR user3Id='".$id."' OR user4Id='".$id."'";
$query = $this->db->query("EXPLAIN EXTENDED SELECT * FROM game WHERE $where");
return $query->result();

Takole gledam po podatkih. Rabim dobiti iz te tabele za single user ID vse njegove vrstice in njegov id je lahko v 4 različnih poljih.

Ne uporabljaj SELECT *, ampak naštej polja ki jih dejansko rabiš, poleg tega poskusi še SELECT COUNT( * ) da vidiš koliko vrstic je izbranih. Mogoče je tu problem - da jih je preveč.

1
  1. Samo zakaj pa rabiš vse naenkrat, ali ne moreš dobiti podatke z agregatnimi funkcijami (SUM, AVG...)? Verjetno ne prikazuješ vseh vrstic naenkrat? Tako da za posamezen izpis uporabiš LIMIT M,N.
  2. V CI naj bi uporabljal query binding: $query = $this->db->query('SELECT * FROM game WHERE user1Id = ? OR user2Id = ? OR user3Id = ?', array($id, $id, $id));
  3. Ko delaš z veliko podatki, predlagam, da ročno sprostiš result object: $results = $query->result(); $query->free_result(); return $results;
2