SQLite
ORDER BY
random sorting
SQL database
database query

SQLite - ORDER BY RAND

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

Developers coming from MySQL often search for ORDER BY RAND() in SQLite when they need random rows. In SQLite, the equivalent function is RANDOM(), but performance and sampling quality depend on table size and query pattern. A good solution balances randomness, latency, and operational simplicity for your workload.

Direct Equivalent in SQLite

SQLite does not implement RAND(), so use RANDOM() instead:

sql
1SELECT id, name
2FROM users
3ORDER BY RANDOM()
4LIMIT 10;

This query is logically straightforward and statistically clean for many use cases. SQLite generates a pseudo-random value per row, sorts by that value, then returns the top rows.

The tradeoff is cost. Random sorting typically scans and sorts a large candidate set, which can become expensive on very large tables.

When ORDER BY RANDOM() Is the Right Choice

Use direct random ordering when:

  • table is small to medium,
  • query frequency is low,
  • exact random ordering is more important than raw speed,
  • operational simplicity matters more than optimization.

Example admin query where readability is valuable:

sql
1SELECT id, title
2FROM articles
3WHERE status = 'published'
4ORDER BY RANDOM()
5LIMIT 5;

For occasional dashboard widgets, this is often good enough and easier to maintain than custom sampling logic.

Why Performance Drops on Large Tables

With many rows, random sort work grows quickly. Even if you only return 10 rows, the engine may process a far larger set before sorting and limiting.

Use EXPLAIN QUERY PLAN to observe query behavior:

sql
1EXPLAIN QUERY PLAN
2SELECT id
3FROM users
4ORDER BY RANDOM()
5LIMIT 10;

If this query is on a hot request path, you should benchmark alternatives using production-like row counts, not toy datasets.

Alternative Sampling Patterns

Pattern 1: Random Offset by Row Count

sql
1SELECT id, name
2FROM users
3LIMIT 1 OFFSET (
4  ABS(RANDOM()) % (SELECT COUNT(*) FROM users)
5);

This avoids full random sort, but still may scan toward the chosen offset and can degrade for huge offsets.

Pattern 2: rowid Probe

sql
1SELECT id, name
2FROM users
3WHERE rowid >= (
4  ABS(RANDOM()) % (SELECT MAX(rowid) FROM users)
5)
6LIMIT 1;

This can be fast but may be biased if many rowid gaps exist from deletions.

Pattern 3: Precomputed Random Key

For frequent random reads, store a random key and index it.

sql
1ALTER TABLE users ADD COLUMN rand_key REAL;
2UPDATE users
3SET rand_key = ABS(RANDOM()) / 9223372036854775808.0;
4
5CREATE INDEX idx_users_rand_key ON users(rand_key);

Then query by threshold:

sql
1SELECT id, name
2FROM users
3WHERE rand_key >= 0.75
4ORDER BY rand_key
5LIMIT 20;

This shifts randomness maintenance to write time and keeps read latency predictable.

Sampling Quality and Product Requirements

Not every feature needs mathematically perfect randomness. Recommendation carousels often benefit more from stable response time and adequate variety than strict uniformity. Define what "random enough" means for your product:

  • strict uniform sample,
  • varied but not uniform rotation,
  • reproducible pseudo-random subset for audits.

If reproducibility is required, generate random IDs in application code using a fixed seed and query by those IDs.

Practical Architecture for High Traffic

For high-traffic systems, do not run expensive randomization in every request. A practical architecture:

  1. background job prepares random ID pools periodically,
  2. request path pulls IDs from cached pool,
  3. detail rows fetched by primary key.

Application-side example:

python
1import sqlite3
2import random
3
4conn = sqlite3.connect("app.db")
5cur = conn.cursor()
6cur.execute("SELECT id FROM users WHERE status = 'active'")
7ids = [row[0] for row in cur.fetchall()]
8
9sample_ids = random.sample(ids, k=min(10, len(ids)))
10placeholders = ",".join("?" for _ in sample_ids)
11cur.execute(f"SELECT id, name FROM users WHERE id IN ({placeholders})", sample_ids)
12rows = cur.fetchall()
13print(rows)
14
15conn.close()

This pattern is easier to control with caching and rate limits.

Common Pitfalls

  • Using MySQL RAND() syntax directly in SQLite queries.
  • Assuming ORDER BY RANDOM() remains fast as table size grows.
  • Choosing rowid probing without evaluating bias from sparse IDs.
  • Benchmarking on tiny local data and shipping untested query plans.
  • Mixing random ordering into deterministic tests and causing flaky assertions.

Summary

  • SQLite uses RANDOM() for random ordering, not RAND().
  • 'ORDER BY RANDOM() is simple and correct, but can be expensive at scale.'
  • Large datasets often need offset, rowid, or precomputed-key strategies.
  • Define randomness requirements before optimizing query shape.
  • Benchmark with realistic data and keep hot request paths latency-safe.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.