Jump to content
php.lv forumi

Saskaitīt unikālus ierakstus konkrētā dienā


AnotherUser

Recommended Posts

Nū, ja problēma ir ātrdarbība, tad ir jādomā par indeksiem. Bet tīklīdz tu sāc taisīt prikolus ar funkcijām uz kolonnām (DATE()), tā var aizmirst, ka tur kaut kas jēdzīgā laikā izpildīsies, jo jāiet cauri būs pilnīgi visiem ierakstiem.

 

Neesmu baigais specs, bet pamēģini gan to subselektu, gan arī galveno selektu izpētīt ar EXPLAIN un pielāgot tabulu, lai pilnībā tiktu izmantoti indeksi. Minu, ka arī vajadzēs glabāt tikai datumu atsevišķā kolonnā, lai var normāli grupēt.

 

Jā pa lielam problēma ir ātrdarbībā.

Dotā tabula ir piemērs un mans sql ir viens no ntajiem subselectiem, tapēc indexi ir salikti optimāli pret visiem sql, kas izpildās šajā tabulā.

 

Ja citi sql izpildās ~125ms tad, šis ~450ms. 

Pamēģināju variantu bez DATE() funkcijas, pāatrinājās par 50ms, kas arī nav gluži variants..

 

Uz doto brīdi tabulā ir ~45K ierakstu, kas ir gandrīz nekas salīdzinājumā ar to apjomu, kas tur gāzīsies iekšā..

Edited by AnotherUser
Link to comment
Share on other sites

  • Replies 35
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Risinājumi:

1)Glabāt šos datus līdz ar šīs tabulas veidošanu, respektīvi, uztaisīt tabulu, kurā glabā unikālos pa datumiem un tad arī kā nāk jauns ieraksts, skatās vai tāds lietotājs ir un, ja nav, palielina šodienas unikālo skaitu.

2)Ja ir grūti esošā kodā to iekļaut, var izveidot ārēju job-u, kurš ik pa laikam ņem jaunos ierakstus un papildina dienu statistikas lapu.

3)Pielikt kešošanu. Mainīties dati var tikai jaunākām dienām, jo laiks uz atpakaļ neiet. Tad var taisīt kveriju dienām un, ja dati nav kešā, taisa pilno kveriju, savādāk no keša.

4)Ja dati var mainīties arī atpakaļejošos datumos, ņemam skala un akka uztaisām distributētu actor-us, kui ielāde atmiņā visu dataset-u un tad ar map reduce metodēm iegūst rezultātu - šajā gadījumā bez problēmām var izveidot algoritmu, kurš miljoniem ierakstu pilno pārlasi veiks zem 10ms, bet tas atkarīgs no tā cik paralēlas skaitļošanas jaudas būs pieejams.

 

P.S. Iesaku uz db skatīties kā uz parastu data storage un netaisīt tur šadas kompleksas atlases, it sevišķi, ja tās tik un tā prasa apskatīt visus ierakstus. Dzīve būs vieglāka.

Edited by codez
Link to comment
Share on other sites

Starp citu manu sākotnējo sql no subquery pārtaisot par JOIN variantu, izpildās uz 1/2 ātrāk, takā tas pagaidām ir ejošākais variants.

 

 

Risinājumi:
1)Glabāt šos datus līdz ar šīs tabulas veidošanu, respektīvi, uztaisīt tabulu, kurā glabā unikālos pa datumiem un tad arī kā nāk jauns ieraksts, skatās vai tāds lietotājs ir un, ja nav, palielina šodienas unikālo skaitu.
2)Ja ir grūti esošā kodā to iekļaut, var izveidot ārēju job-u, kurš ik pa laikam ņem jaunos ierakstus un papildina dienu statistikas lapu.
3)Pielikt kešošanu. Mainīties dati var tikai jaunākām dienām, jo laiks uz atpakaļ neiet. Tad var taisīt kveriju dienām un, ja dati nav kešā, taisa pilno kveriju, savādāk no keša.
4)Ja dati var mainīties arī atpakaļejošos datumos, ņemam skala un akka uztaisām distributētu actor-us, kui ielāde atmiņā visu dataset-u un tad ar map reduce metodēm iegūst rezultātu - šajā gadījumā bez problēmām var izveidot algoritmu, kurš miljoniem ierakstu pilno pārlasi veiks zem 10ms, bet tas atkarīgs no tā cik paralēlas skaitļošanas jaudas būs pieejams.

P.S. Iesaku uz db skatīties kā uz parastu data storage un netaisīt tur šadas kompleksas atlases, it sevišķi, ja tās tik un tā prasa apskatīt visus ierakstus. Dzīve būs vieglāka.

 

1. Atkrīt jo tad pie ierakstīšanas man būs jātaisa selects, ko es nevaru atļauties mega lielā traffika dēļ.

2. Atkrīt jo statistika nepieciešama in live.

3. Tas atrisinās iepriekšējo dienu statistikas ielādi, bet aktuāli ir šodien un tulīt.

4. Var lūdzu šo nedaudz detalizētāk, scala/akka/distributētu actor-us/... ?

 

Paldies.

Link to comment
Share on other sites

1. Atkrīt jo tad pie ierakstīšanas man būs jātaisa selects, ko es nevaru atļauties mega lielā traffika dēļ.

Reāli jau vienkārši selecti pēc indeksa ir par kārtu ātrāki par insertiem. Bet vajag pamērīt.

 

3. Tas atrisinās iepriekšējo dienu statistikas ielādi, bet aktuāli ir šodien un tulīt.

Var kešā glabāt ari šodienas statistiku, kuru vāc pie apmeklējuma, bet šeit būs tik un tā būs selects un inserts no 1. varianta.

 

4. Var lūdzu šo nedaudz detalizētāk, scala/akka/distributētu actor-us/... ?

http://akka.io/

Ideja ir tāda, ka atlases algoritms strādā kā aktors, viņam padod datus, vai uztaisa, ka dati pieejami un padod intervālu,kuru viņam jāapstrādā.

Actori var strādāt paralēli gan uz viena servera (izmantot uzreiz visas kores), gan uz vairākiem. Tātā veidā, piemēram, var n-kāršot darba izpildes ātrumu.

Plus pati skala vēl ir krietni ātrāka kā PHP. Piemēram, ja tev ir 10 miljoni ierakstu, kuru pilna pārlase ar mysql aizņemtu kādas 5 sekundes, ar php kādas 100 sekundes, ar skalu kādas 1-2 sekundes. Tad vēl sadalot uzdevumu vairākiem aktoriem, piemēram, (4 servi ar 4 korēm) 16 aktoriem, 1 sekundes darbs tiek izpildīts aptuveni 40ms, kas miljons ierakstu gadījumā būs 4ms.

Bet, ja ir šito nav bijusi saskarsme, būs kārtīgs learning curve.

 

Ir vēl citi paralēlu skaitļošanu fw, piem., gridgrain, hadoob, gearman, utml.

Edited by codez
Link to comment
Share on other sites

Ir vēl citi paralēlu skaitļošanu fw, piem., gridgrain, hadoob, gearman, utml.

 

Paldies, būs ko gremot.

 

 

Uzmet dumpu kaut kur failiem.lv, lai var paspēlēties.

 

http://failiem.lv/u/agdqhtw?k=57fd6f0c

 

Ar JOIN tomēr nevar to realizēt..

tapēc SQL uz doto brīdi ir 

SELECT COUNT(DISTINCT `cId`) as uniqs
FROM `thread_stats` as ts
WHERE ts.tId = 1
AND (SELECT DATE(ts2.`date_hour`) FROM `thread_stats` as ts2 WHERE ts.cId = ts2.cId LIMIT 1 ) = '2013-12-15' AND DATE(ts.`date_hour`) = '2013-12-15'

~450ms

Edited by AnotherUser
Link to comment
Share on other sites

Dīvaini tur tie dati. Man sanāk, ka unikāli ir faktiski visi un datums ir tikai viens. Atkārtojas tikai kādi 115 cid un visi divreiz. Izpildās momentā.

Jā, tur ir viena diena un principā vienas stundas intervālā, tapēc arī ir 99% unikālie, bet man arī ar šādiem datiem ir ~400ms.

 

"Momentā" tas ir cik?

Tu uz Percona, vai mysql testē?

Un kāds dzelzis?

Edited by AnotherUser
Link to comment
Share on other sites

OK, tas momentā ir ~0.759sec ar cold cache :D. Laikam padaudz. Atkārtoti 0.0004 sec.

Tava versija ~1.4sec.

Dzelzis: 2.2Ghz Opteron 2427

Percona 5.1

 

SELECT SUM(uniq) FROM (
SELECT
	COUNT(DISTINCT t1.`cid`) as uniq
FROM
	`thread_stats` t1
WHERE
	t1.dt = '2013-12-15' AND t1.cid NOT IN (SELECT cid FROM `thread_stats` t2 WHERE dt != '2013-12-15' GROUP BY t2.cid)
GROUP BY
	t1.cid
) as ss;
Es atdalīju to date atsevišķā kolonnā un index uz (dt,cid)
Link to comment
Share on other sites

0.33, izvācot group by no subkverija.

SELECT SUM(uniq) FROM (
SELECT SQL_NO_CACHE
	COUNT(DISTINCT t1.`cid`) as uniq
FROM
	`thread_stats` t1
WHERE
	t1.dt = '2013-12-15' AND t1.cid NOT IN (SELECT DISTINCT cid FROM `thread_stats` t2 WHERE dt != '2013-12-15')
GROUP BY
	t1.cid
) as ss;

 

Thanx ;)

 

 

Mhhm.., bet ir tomēr gļuks,

pamēģini ieliec vēl vienu ierakstu ar 14 datumu, kura cId būs arī 15. datumā, velkam ārā par 15. datumu viss pareizi -1 no iepriekšējā rezultāta, bet paskatoties 14. datumu jābūt 1 unikālajam, a mums 0 :/

WHERE dt != '2013-12-15'

Ir problēma

Edited by AnotherUser
Link to comment
Share on other sites

http://dev.mysql.com/doc/refman/5.1/en/insert-on-duplicate.html

 

Starp citu manu sākotnējo sql no subquery pārtaisot par JOIN variantu, izpildās uz 1/2 ātrāk, takā tas pagaidām ir ejošākais variants.

 

 

 

1. Atkrīt jo tad pie ierakstīšanas man būs jātaisa selects, ko es nevaru atļauties mega lielā traffika dēļ.

 

Paldies.

 

http://dev.mysql.com/doc/refman/5.1/en/insert-on-duplicate.html

 

pa kruto protams būtu kāds streaming map reduce's

Edited by spainis
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

×
×
  • Create New...