Millions of 3D points How to find the 10 of them closest to a given point?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
If you have millions of 3D points and only need the 10 closest to a target point, the key optimization is to avoid fully sorting the entire dataset. Computing every distance may still be necessary for a single brute-force query, but keeping only the best k candidates is much cheaper than ordering all n points.
The right algorithm depends on how many queries you need to answer. For one query, a linear scan with a heap is usually strong. For many repeated queries, build a spatial index such as a k-d tree.
Start with Squared Distance
For nearest-neighbor ranking, you do not need the actual Euclidean distance. You only need a value that preserves the ordering, so squared distance is enough.
For target point (tx, ty, tz) and candidate (x, y, z), compare:
(x - tx)^2 + (y - ty)^2 + (z - tz)^2
Skipping the square root saves work and keeps the math simple.
For One Query, Use a Max-Heap of Size k
If you only need one query result, scan the points once and keep the current best 10 in a max-heap. In Python, heapq is a min-heap, so a common trick is to push negative distances.
This runs in O(n log k). With k = 10, the heap maintenance is tiny compared with sorting everything.
Why Full Sorting Is Usually Wasteful
A full sort is O(n log n). That is appropriate if you need all points in order, but not when you only care about the first 10.
For example, with millions of points and k = 10, the difference between log 10 and log n matters. The heap approach also uses less memory because it never stores more than k candidate points outside the input.
For Many Queries, Build a Spatial Index
If the dataset is static and you need lots of nearest-neighbor queries, brute force becomes wasteful. Build a spatial index once and reuse it.
Popular choices include:
- k-d trees for exact nearest neighbors in low dimensions
- ball trees for some alternative distance structures
- approximate nearest-neighbor systems when speed matters more than exactness
In 3D, k-d trees are often a very good fit because the dimension is low and geometric pruning remains effective.
Data Layout and Libraries Matter
With millions of points, performance is often limited by memory bandwidth and language overhead rather than arithmetic alone. If the data already lives in NumPy arrays, SciPy, Faiss, PCL, or another point-cloud library, use the optimized tools there instead of hand-written Python loops for production code.
The algorithmic principles stay the same:
- use squared distance for ranking
- avoid full sorts when only top
kmatters - pre-index data if queries repeat
Streaming and Out-of-Core Cases
The heap approach works nicely even when the full dataset does not fit in memory. Because it only keeps k best candidates, you can stream points from a file or network source and still produce the exact result for a single query.
That is a strong practical advantage over methods that assume random access to the entire dataset.
Common Pitfalls
The most common mistake is sorting all distances when only the 10 nearest are needed. Another is computing square roots for every comparison even though squared distance preserves the same ranking. Developers also sometimes reuse the one-query heap approach for thousands of repeated queries, when a k-d tree or approximate nearest-neighbor index would be a much better long-term choice. Finally, object-heavy point representations can erase the benefits of a good algorithm if the implementation spends most of its time on allocation and Python overhead.
Summary
- For one query, scan all points and keep a max-heap of the best
kcandidates. - Compare squared distances instead of Euclidean distances with square roots.
- The heap approach is
O(n log k), which is much better than full sorting whenkis small. - For many repeated queries, build a spatial index such as a k-d tree.
- Use optimized numeric or point-cloud libraries when the dataset is truly large.

