[development] Drupal 7 Entities - view random node

Larry Garfield larry at garfieldtech.com
Mon Jan 24 02:33:11 UTC 2011


The only way I can see for a separate lookup table to help would be to 
prepopulate it with your desired filters and an arbitrary autoinc field.  So 
you would do something like:

INSERT INTO {mytemp} SELECT nid FROM {node} WHERE type='quote';

And then rebuild that (incrementally or full) every time you add or remove a 
quote node.  Then to select, you would select one int at random between 1 and 
COUNT(*) in mytemp, then pull that record.

The above makes the actual "fetch one at random" operation almost O(1), but 
you need to create and maintain that 

Actually, I just found this in the MySQL manual in user comments:

SELECT FLOOR(RAND() * COUNT(*)) AS rand_row FROM {mytemp};
SELECT nid FROM {mytemp} LIMIT $rand_row, 1;

That could actually be faster, at the cost of being two queries so there are 
technically potential race conditions.  (Unlikely to be a problem in practice, 
but still there.)  I've not tried the above; I just saw it and thought it was 
cool. :-)  (It's also MySQL-specific. I don't know if the same thing would 
work well on other databases.)

The MySQL manual has a couple of other suggestions in user comments, too:
http://dev.mysql.com/doc/refman/5.0/en/select.html

--Larry Garfield

On Sunday, January 23, 2011 8:12:08 pm nan wich wrote:
> Thanks, Larry, that make me feel a bit better.
> 
> The suggestion is to keep a separate table of applicable nodes, generate a
> random number from the number of records, and get that record. Your
> explanation seems to indicate that one is simply spreading the "overhead"
> out over time - and probably increasing it in total, maybe. Given that the
> block can be refreshed on every page load, and a new node
> created relatively infrequently, I can also see that there may be some
> merit when the number of nodes gets fairly large. Maybe something like
> "SELECT n.* FROM {quotes_random} r INNER JOIN {node} n ON n.nid = r.nid
> WHERE r.row_num = 1 + RAND() * (SELECT MAX(row_num) FROM
> {quotes_random})". (Sorry for the D6 version; it would take me a much
> longer time to construct in D7.)
> 
> 
> Nancy
>  
> Injustice anywhere is a threat to justice everywhere. -- Dr. Martin L.
> King, Jr.
> 
> 
> 
> ________________________________
> 
> From: Larry Garfield
> I don't know that I've ever tried it with 12k nodes so I can't say from
> experience.
> 
> Randomization is a tricky subject.  The common method, which Views uses as
> does the ->orderRandom() method of DBTNG, boils down to adding a random
> number as a new column for each record, ordering by that, and then (in
> this case) discarding all but the first record.  That involves a
> linear-growth creation for the new column (a fixed additional cost per
> record) and then an integer ordering.  Assuming the sorting function in
> the SQL database is sane (which if it isn't you need a new database), that
> should be an n*log n algorithm. (That's as fast as a sorting algorithm can
> get.)


More information about the development mailing list