Don't all databases support efficient TABLESAMPLE with a number of rows? Postgres probably does.
Tablesample is not accurate as far as I remember.
How to Optimize Order by Random()
11–20 of 37 posts
Re: How to Optimize Order by Random()
#12Earlier quoted context omitted.
It doesn't make any sense at all. Draw the Voronoi diagram; the cells will be of non-uniform size, so some points are much more likely to be picked than others. And why is this 2D? 2D doesn't give you any more randomness than 1D, it's just obfucscation. If you computed the cell points anew for each sampling, it would indeed be random. But for repeated sampling, you've made up a very skewed distribution, where the suc…
It‘s the best randomness that is achievable i am aware of. Do you have ideas for improvements? It‘s 2d because databases do not have kNN with index support for a single float value. And without kNN you are building approach #2 with all of it‘s problems.
I've Googled around but didn't find anything about this trick:
You can calculate a score and do something like ORDER BY RAND() * score to bias towards certain rows. This could be useful, e.g. you want to randomly show your most profitable items. The kNN method seems harder to generalize.
Re: How to Optimize Order by Random()
#13Earlier quoted context omitted.
It doesn't make any sense at all. Draw the Voronoi diagram; the cells will be of non-uniform size, so some points are much more likely to be picked than others. And why is this 2D? 2D doesn't give you any more randomness than 1D, it's just obfucscation. If you computed the cell points anew for each sampling, it would indeed be random. But for repeated sampling, you've made up a very skewed distribution, where the suc…
It‘s the best randomness that is achievable i am aware of. Do you have ideas for improvements? It‘s 2d because databases do not have kNN with index support for a single float value. And without kNN you are building approach #2 with all of it‘s problems.
Anyway, if you had this blue noise, whether 1d or 2d, would still not solve your problem; once you start deleting points, you lose your beautiful properties of uniform voronoi cell sizes and your back to square one.
Re: How to Optimize Order by Random()
#14Wouldn't you typically solve this kind of problem with rejection sampling? Pick a random ID - if it's already in the result set or deleted, try again. I suppose this cannot be neatly expressed in SQL though?
Re: How to Optimize Order by Random()
#15Re: How to Optimize Order by Random()
#16Points inside a cluster of other points will be less likely to be picked than points that are in a relatively empty region of space.
Re: How to Optimize Order by Random()
#17I think using a range of rows is overkill, at least for row-stores. And also in the majority of cases random rows are preferred than a range.
In the case where the table has a simple Primary Key the query is easier. Select all the valid PKs (rows) ordered by random and then limit.
SQLite gives access to the rowid making this query even simpler and likely faster (no need for PK and the query works on tables without a PK).
SELECT * FROM test
WHERE rowid IN
(SELECT rowid FROM test
ORDER BY random() LIMIT 10);
or with a more verbose JOIN: SELECT * FROM test JOIN
(SELECT rowid as rid
FROM test ORDER BY random() LIMIT 10) AS srid
ON test.rowid = srid.rid;
The database engine tracks existing rows by some sort of id with its own internal rowid/PK index structure. Materializing these IDs should not be that expensive and as it's sequential access it should be pretty fast. The expensive part is the ORDER BY random().If your table is truly big, say billions of rows, this could be improved by reducing the list of rowids with a WHERE clause.
But don't overdo it or you'll affect the truer randomness. For most cases just reduce to hundreds of thousands.
For whatever reason, using this filtered (WHERE), the JOIN query to generates a seemingly better SQLite plan.
SELECT * FROM test JOIN
(SELECT rowid as rid FROM test
WHERE random() % 10 = 0 -- Reduce rowids
ORDER BY random() LIMIT 10) AS srid
ON test.rowid = srid.rid;
The manual '% 10' filter could be improved with some calculation of the table's row count, minding small tables. Left as exercise.Re: How to Optimize Order by Random()
#18Wouldn't you typically solve this kind of problem with rejection sampling? Pick a random ID - if it's already in the result set or deleted, try again. I suppose this cannot be neatly expressed in SQL though?
Re: How to Optimize Order by Random()
#19This not a random selection. It has the same issues as the 1-dimensional case, and will not sample uniformly. Points inside a cluster of other points will be less likely to be picked than points that are in a relatively empty region of space.
Re: How to Optimize Order by Random()
#20This not a random selection. It has the same issues as the 1-dimensional case, and will not sample uniformly. Points inside a cluster of other points will be less likely to be picked than points that are in a relatively empty region of space.
You can fix this by looping the space around once you reach the edge but good luck expressing that in SQL.
You could also fix it by putting them on a sphere I think, though picking a random point on a sphere is exactly the easiest thing to do.