[ pisac @ 16.04.2016. 04:04 ] @
Imam tabele "cdr" i "cdrmoj"

Code:

mysql> select count(*) from cdr;
+----------+
| count(*) |
+----------+
|   234362 | 
+----------+
1 row in set (2,86 sec)

mysql> select count(*) from cdrmoj;
+----------+
| count(*) |
+----------+
|    43738 | 
+----------+
1 row in set (2,60 sec)


Kao što se vidi, select count(*) se izvršava do 3 sekunde.

E onda sam napravio view
Code:

Create View | cdrbitno | CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `cdrbitno` AS select
`cdrmoj`.`timestamp` AS `timestamp`,
`cdrmoj`.`channel` AS `channel`,
`cdrmoj`.`callingpres` AS `callingpres`,
`cdrmoj`.`cid_name` AS `cid_name`,
`cdrmoj`.`cid_num` AS `cid_num`,
`cdrmoj`.`cid_dnid` AS `cid_dnid`,
`cdr`.`duration` AS `duration`,
`cdr`.`billsec` AS `billsec`,
`cdrmoj`.`out_radnja` AS `out_radnja`,
`cdrmoj`.`out_broj` AS `out_broj`,
`cdrmoj`.`out_komanda` AS `out_komanda`,
`cdr`.`lastapp` AS `lastapp`,
`cdr`.`lastdata` AS `lastdata`,
`cdrmoj`.`hangupcause` AS `hangupcause`,
`cdrmoj`.`snimak` AS `snimak`,
`cdrmoj`.`pocetak` AS `pocetak`,
`cdrmoj`.`kraj` AS `kraj`,
`cdrmoj`.`id` AS `id`
 from (`cdrmoj` left join `cdr` on((`cdrmoj`.`id` = `cdr`.`userfield`)))


I "slučajno" napravio upit select count(*) na toj "tabeli", i taj upit traje već oko 12 sati... i ne znam kad će da završi.

Ima li neko nešto da prokomentariše

[ bogdan.kecman @ 16.04.2016. 15:59 ] @
ako bi tabele cdr i cdrmoj myisam onda count(*) bez where is te tabele ne "broji" nista nego procita vrednosti iz metadata bloka u kom pise koliko slogova ima tabela. myisam moze da odrzava taj metablok zato sto ima samo table level lock tako da to nije problem. innodb sa druge strane mora da "izbroji".. to ne traje satima posto verovatno imas primary key tako da se broji direkt iz indexa, ne mora da se prodje cela tabela.. sad obzirom da tebi taj select traje 3 sekunde rekao bi da nisu myisam nego innodb mada ne mora da znaci, moguce da si cekao 3 sec na neki lock..

onda si pustio upit cdr*cdrmoj bez where i rekao mu da to izbroji, nema indexa, nema mogucnosti da se ista preterano optimizuje .. kreira ti se ogromna tmp tabela na disku pa kad zavrsi kreiranje iste onda ce da krene da broji.. takav upit moze danima da traje



[ jablan @ 16.04.2016. 16:34 ] @
3 sekunde za count(*) tabele sa 40k redova? Na čemu se to vrti, na nokiji 3310?
[ pisac @ 17.04.2016. 04:35 ] @
To je bilo dok je komp radio i nešto drugo (između ostalog i ovo brojanje o kome je reč).

Sada je:
Code:
mysql> select count(*) from cdrmoj;
+----------+
| count(*) |
+----------+
|    43763 |
+----------+
1 row in set (0,36 sec)


Inače, sve tabele kod mene su InnoDB zato što sam jednom prilikom utvrdio da mi zbog MyISAM stane ceo VoIP server ako nešto u jednom od razgovora zapne u nekom upisu/čitanju šta ja znam (ne sećam se tačno šta beše uzrok), kada sam stavio InnoDB problemi sa blokiranjem su odmah nestali i nema ih ma koliko terorisao server.

Nego, kako ja da rešim ovo celodnevno brojanje view-a a da ne menjam InnoDB? Problem mi je što se totalno blokira i php sesija onog naloga koji je "slučajno" kliknuo na pregled te tabele (pošto mi php strana radi prvo brojanje pa onda prikaz), pa dotični nesrećnik koji je kliknuo na pogrešnu tabelu mora da briše cookie sa kompjutera da bi mogao da se uloguje ponovo i gleda nešto drugo.

[Ovu poruku je menjao pisac dana 17.04.2016. u 06:04 GMT+1]
[ bogdan.kecman @ 17.04.2016. 05:07 ] @
ima onaj stari vic kad je muja bio kod doktora pa kuka doci da ga boli kad "Savije ruku ovako" .. na sta mu doca kaze, pa nemo tako da savijas ruku ... to ti je otprilike odgovor za tvoje pitanje ..
taj rezultat deluje da je 40GB tabela, nagadjem bez explain-a...

"naloga koji je "slučajno" kliknuo na pregled te tabele (pošto mi php strana radi prvo brojanje pa onda prikaz)"

ne bi komentarisao ovu strasnu izjavu

no, za pocekat, koji je to uopste mysql? da li je uopste mysql? marija i xtra trenutno jos uvek ne znaju za materialized temp table, mysql 5.7 to ume

procitaj: http://mysqlserverteam.com/derived-tables-in-mysql-5-7/

mozda ti da neku ideju

dalje, sta ti kaze uopste explain za select * iz tog view-a, sta ti kaze select count(*) iz istog view-a?

sta ti kaze profiling posle bilo kakvog select-a iz tog view-a?

kolika ti je tmp tabela napravljena posle X sati rada tog count(*) u /tmp/#* ?



[ pisac @ 17.04.2016. 21:17 ] @
Ne mogu da verujem.

Prvo sam mislio da će neko trebati da mi explain kako se koristi explain , ali sam vrlo lako ustanovio da mi cdr tabela nema indekse!
Onda sam dodao index na userfield polje i sada se count izvršava za

Code:

ysql> select count(*) from cdrbitno;
+----------+
| count(*) |
+----------+
|   221866 |
+----------+
1 row in set (1,59 sec)


Nisam mogao da poverujem da je samo dodavanje indeksa ubrzalo brojanje više od 40 000 puta, pa sam malo proveravao, ali - to je to.

Inače mysql je neki stari 5.0.nešto.
[ djoka_l @ 18.04.2016. 08:21 ] @
Ne mogu da verujem da ne možeš da veruješ.

Kada nema indeksa, upit dovuče 10 milijardi redova da izvrši upit.
Kada staviš indeks, pročitaš 220 hiljada redova.
[ pisac @ 18.04.2016. 21:46 ] @
Ustanovio sam da sortiranje po polju billsec ne mogu nikako da napravim da radi u razumnom vremenu, čak ni sa indeksima. Billsec pripada cdr tabeli koja ima više zapisa, a sortiranja po poljima koja pripadaju cdrmoj tabeli rade bez problema.

Ima li nekog rešenja za taj problem?

[ bogdan.kecman @ 18.04.2016. 21:52 ] @
koliko je velika tabela sa rezultatom?
ima tupavi ne lako resivi bug sa mysql-om da koristi pogresan index kada
se koristi sortiranje u nekom slucaju tako da forsiranje drugog indexa
moze da resi problem ... uradi explain kad je brzo i explain kad je
sporo i u toj sporoj varijanti forsiraj indexe kad je brzo
[ pisac @ 19.04.2016. 09:59 ] @
Pa tabela je nekih 220k redova.

Koliko mi je explain objasnio, ako se ja dovoljno razumem u baze, čini mi se da zaista koristi pogrešan index (valjda bi trebao da koristi billsec za sortiranje po tom polju, a ne userfield):

Code:

mysql> explain SELECT * FROM cdrbitno  ORDER by billsec ASC limit 20 offset 0;

+----+-------------+--------+------+---------------+-----------+---------+-----------------+-------+---------------------------------+
| id | select_type | table  | type | possible_keys | key       | key_len | ref             | rows  | Extra                           |
+----+-------------+--------+------+---------------+-----------+---------+-----------------+-------+---------------------------------+
|  1 | SIMPLE      | cdrmoj | ALL  | NULL          | NULL      | NULL    | NULL            | 48507 | Using temporary; Using filesort | 
|  1 | SIMPLE      | cdr    | ref  | userfield     | userfield | 8       | aster.cdrmoj.id |     2 |                                 | 
+----+-------------+--------+------+---------------+-----------+---------+-----------------+-------+---------------------------------+
2 rows in set (0,01 sec)

mysql> 
mysql> 
mysql> show indexes from cdr;
+-------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name  | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| cdr   |          1 | uniqueid  |            1 | uniqueid    | A         |      243988 |     NULL | NULL   |      | BTREE      |         | 
| cdr   |          1 | userfield |            1 | userfield   | A         |      121994 |     NULL | NULL   |      | BTREE      |         | 
| cdr   |          1 | billsec   |            1 | billsec     | A         |          64 |     NULL | NULL   |      | BTREE      |         | 
+-------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
3 rows in set (0,10 sec)
[ bogdan.kecman @ 19.04.2016. 10:03 ] @
a sta kaze bez order by kada radi brzo?
[ pisac @ 19.04.2016. 10:56 ] @
Pa isto to samo nema extra koje je prazno.
[ _owl_ @ 19.04.2016. 10:58 ] @
Index nad userfield-om se najverovatnije koristi zbog join-a iz definicije view-a.
[ bogdan.kecman @ 19.04.2016. 11:05 ] @
jbg nagadjamo do prekosutra, aj lepo daj sve informacije ... create od obe tabele, show table status od obe tabele, explain view-a, ne select iz view-a nego direktno

explain EXTENDED select
`cdrmoj`.`timestamp` AS `timestamp`,
`cdrmoj`.`channel` AS `channel`,
`cdrmoj`.`callingpres` AS `callingpres`,
`cdrmoj`.`cid_name` AS `cid_name`,
`cdrmoj`.`cid_num` AS `cid_num`,
`cdrmoj`.`cid_dnid` AS `cid_dnid`,
`cdr`.`duration` AS `duration`,
`cdr`.`billsec` AS `billsec`,
`cdrmoj`.`out_radnja` AS `out_radnja`,
`cdrmoj`.`out_broj` AS `out_broj`,
`cdrmoj`.`out_komanda` AS `out_komanda`,
`cdr`.`lastapp` AS `lastapp`,
`cdr`.`lastdata` AS `lastdata`,
`cdrmoj`.`hangupcause` AS `hangupcause`,
`cdrmoj`.`snimak` AS `snimak`,
`cdrmoj`.`pocetak` AS `pocetak`,
`cdrmoj`.`kraj` AS `kraj`,
`cdrmoj`.`id` AS `id`
from (`cdrmoj` left join `cdr` on((`cdrmoj`.`id` = `cdr`.`userfield`)))

i

explain EXTENDED select
`cdrmoj`.`timestamp` AS `timestamp`,
`cdrmoj`.`channel` AS `channel`,
`cdrmoj`.`callingpres` AS `callingpres`,
`cdrmoj`.`cid_name` AS `cid_name`,
`cdrmoj`.`cid_num` AS `cid_num`,
`cdrmoj`.`cid_dnid` AS `cid_dnid`,
`cdr`.`duration` AS `duration`,
`cdr`.`billsec` AS `billsec`,
`cdrmoj`.`out_radnja` AS `out_radnja`,
`cdrmoj`.`out_broj` AS `out_broj`,
`cdrmoj`.`out_komanda` AS `out_komanda`,
`cdr`.`lastapp` AS `lastapp`,
`cdr`.`lastdata` AS `lastdata`,
`cdrmoj`.`hangupcause` AS `hangupcause`,
`cdrmoj`.`snimak` AS `snimak`,
`cdrmoj`.`pocetak` AS `pocetak`,
`cdrmoj`.`kraj` AS `kraj`,
`cdrmoj`.`id` AS `id`
from (`cdrmoj` left join `cdr` on((`cdrmoj`.`id` = `cdr`.`userfield`)))
order by stagodvecoces

mozes da dodas i isto to samo umesto EXTENDED stavis FORMAT=json


[ djoka_l @ 19.04.2016. 11:12 ] @
billsec je užasan kandidat za indeks. Samo 64 distinct vrednosti u tabeli od 240000 slogova. Da je u pitanju data warehouse, pa da staviš bitmap indeks nad tim poljem, ali ovako je i bolje što ga ne koristi.
[ anon115774 @ 19.04.2016. 16:21 ] @
A da uradis to sortiranje iz dva koraka?

Prvi korak da dovuces podatke (filtrirane i nesortirane) u temp tabelu.

Drugi korak sortiras temp tabelu.