Devo calcolare l'intensità di un post su richiesta o precalcolarlo?

1

Qui è l'algoritmo hot di Reddit:

cpdef double _hot(long ups, long downs, double date):
    """The hot formula. Should match the equivalent function in postgres."""
    s = score(ups, downs)
    order = log10(max(abs(s), 1))
    if s > 0:
        sign = 1
    elif s < 0:
        sign = -1
    else:
        sign = 0
    seconds = date - 1134028003
    return round(order + sign * seconds / 45000, 7)

Il mio cervello dice che il calore di un post dovrebbe essere calcolato su ogni richiesta perché i vecchi post dovrebbero avere un punteggio basso di hotness.

Ho implementato questa funzione in MySql ma, come puoi immaginare, è lenta. Ci sono anche indici molto lenti.

E poi penso di aggiornare il campo hotness del post su ogni upvote o downvote del post. Supponiamo di avere un post appena pubblicato ora e ha 100 upvote e 1 downvote ed è hotness 78 (esempio). Ma non ottiene voti per 3 giorni. Dopo 3 giorni appare un nuovo post e ottiene 100 upvotes e 1 downvote e ha 78 punti. Se sto aggiornando il punteggio di hotness sui voti, il post di 3 giorni e il nuovo post verranno visualizzati insieme. Ma in teoria, il post di 3 giorni non dovrebbe nemmeno comparire in prima pagina.

Qual è il metodo più attuabile da implementare per questa situazione?

    
posta Cnkt 24.01.2013 - 10:45
fonte

3 risposte

2

My brain says hotness of a post should be calculated on every request because old posts should have a low hotness score.

Il tuo cervello è sbagliato. Il date nella funzione è l'ora originale del post. Il valore della funzione è indipendente dal tempo di calcolo e rimane costante tra i voti. Tenendo presente questo, è necessario aggiornarlo solo quando i voti sono espressi. Basta memorizzare il numero nel database e amp; query su una colonna indicizzata. I problemi di prestazioni scompaiono.

Questo riguarda anche il tuo secondo numero: un post con 100 upvotes fatti oggi sarà sempre più caldo di un post a +100 fatto ieri.

    
risposta data 24.01.2013 - 20:18
fonte
2

Quando si hanno processi a esecuzione prolungata, è meglio non rendere una richiesta dipendente dal completamento del processo. Se dare all'utente il punteggio più caldo più aggiornato non è della massima importanza, potresti probabilmente farla franca assegnando all'utente un punteggio vicino relativamente .

Invece di avviare questo calcolo su ogni richiesta, è necessario disporre di una sorta di meccanismo per attivare un processo in background che estrae i dati necessari, calcola l'hotness e aggiorna un valore impostato per il post. Il tuo database vorrebbe qualcosa come:

/* Other Post Data */
postViews - BIGINT // Number of actual post views
postViewsLastRun - BIGINT // Number of post views at last hotness job
lastViewed - DATETIME  // Timestamp of the last viewing of the post
lastCalculated - DATETIME // Timestamp of the last hotness job
hostness - INT // Hotness rating to display to the user

A seconda di ciò che ritieni appropriato, potresti voler ricalcolare l'hotness dopo ogni n numero di visualizzazioni di post, o forse vuoi calcolarlo ogni ora.

Per il primo, devi tirare la colonna postViews e postViewsLastRun , incrementarla e controllarla rispetto alla soglia dei post. Se la differenza tra postViewsLastRun e postViews soddisfa o supera la soglia, ti consigliamo di aggiornare la postViewsLastRun di un processo con una sorta di Job Scheduler per gestire l'elaborazione e l'aggiornamento del punteggio di hotness.

Per quest'ultimo, è necessario eseguire una procedura pianificata, ad esempio ogni ora. Verificherebbe se ci fosse se il post fosse visualizzato o meno all'interno della sua soglia di tempo controllando l'ora corrente con la colonna lastCalculated . Supponendo che i criteri per un altro calcolo siano soddisfatti, si sposterà un lavoro per gestire l'elaborazione e continuerà a controllare i dati rilevanti per altri post nel database.

Ora ogni volta che un utente richiede i dati di un post, è possibile fornire loro una valutazione di accuratezza relativamente accurata, basata su criteri precisi, e non causerà alcuna latenza a causa di un calcolo a lungo termine. Nel tuo caso, non vorrai che vengano visualizzate informazioni obsolete, perché ciò causerebbe un'esperienza utente negativa, quindi ti consigliamo di utilizzare l'approccio che viene eseguito a intervalli regolari di tempo.

    
risposta data 24.01.2013 - 14:13
fonte
1

A mio modesto parere (non un esperto) è che puoi aggiornare l'hotness del db su qualsiasi upvote o downvote ma per distinguere i nuovi post da quelli vecchi puoi applicare un qualche tipo di equazione al caldo che tieni nel DB. Qualcosa come:

hotnesss = hotness_from_up_and_down_votes_in_DB + (150 - (today-post_date)) + ((15- (today-last_vote_date)) * 10)

questo significa che i post avranno meno hotness con il tempo e i post con più di 150 giorni iniziano a ricevere hotness negativa per questo e anche il post che ha avuto voti negli ultimi 15 giorni si riscalda per quello e dopo 15 giorni senza voti iniziano a ricevere hotness negativo

se non vuoi hotness negativi puoi farlo in questo modo:

hotnesss = hotness_from_up_and_down_votes_in_DB + (150 / ((today-post_date) + 1)) + ((15 / (today-last_vote_date)) * 10)

stessa cosa ma con il tempo inizi a ricevere 0 hotness invece di negative

NOTA: il + 1 su "((today-post_date) + 1))" serve solo a impedire che i post di oggi dividano 150 per 0

NOTA: è possibile impostare le soglie a piacere (150 e 15 giorni). Se vuoi una migliore equazione puoi osservare le equazioni logaritmiche o esponenziali.

Spero che ti sia di aiuto.

    
risposta data 24.01.2013 - 13:59
fonte

Leggi altre domande sui tag