SQLite Forum

How to rerank one row in a big set of rows?
Login
I don't have a solution to what you describe, but here are some thoughts.

If you make your *rank* the `id PRIMARY KEY` column, as an [alias to the ROWID][ROWID],  
then updating the ranks means physically moving the rows around, rebalancing the BTREE,  
which means a lot of IO. Very expensive.

While if the *rank* is a separate and explicit column of its own,  
then updating it means updating the pages with actually modified rows only.

If you make queries by that `rank` column, then you need an index on it though.  
So the index will need updating too, but then you don't need to *move* the `item` columns,  
as when `id` and `rank` are one-and-the-same and the PK.

If you ranks change often, that's a problem indeed. You could switch to a floating point rank,  
to insert *in-the-middle*, w/o disturbing surrounding rows, but that only works so many times,  
you eventually run out of precision. But if you can detect [those conflicts when they arise][UPSERT],  
you've at least reduced the frequency of re-ranking the *tail/rest* of a rank-update.

A similar strategy is to split your rank in two, the primary and secondary.  
The latter starts out at zero, and when re-ranking, you just update that one instead of the primary,  
again limiting the number of rows that need updating on re-ranks. Now some rows share a primary rank  
(after 1 or more reranking), but not a secondary one, and you need to index/order-by both ranks of course,  
but again, it's a strategy to limit to number of rows affected by a rerank.

In both cases (REAL ranks or SPLIT ranks),  
once in a while you probably want to pay for a full rerank to go back to *INT-reals* or *ALL-0-sub-ranks*.

I'm just thinking aloud here, I haven't tried any of the above. --DD

[ROWID]: https://www.sqlite.org/lang_createtable.html#rowid
[UPSERT]: https://www.sqlite.org/lang_UPSERT.html