Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the most efficient way to store a sort-order on a group of records in a database? [closed]

Tags:

Assume PHP/MYSQL but I don't necessarily need actual code, I'm just interested in the theory behind it.

A good use-case would be Facebook's photo gallery page. You can drag and drop a photo on the page, which fires an Ajax event to save the new sort order. I'm implementing something very similar.

For example, I have a database table "photos" with about a million records:

photos id : int, userid : int, albumid : int, sortorder : int, filename : varchar, title : varchar

Let's say I have an album with 100 photos. I drag/drop a photo into a new location and the Ajax event fires off to save on the server.

Should I be passing the entire array of photo ids back to the server and updating every record? Assume input validation by "WHERE userid=loggedin_id", so malicious users can only mess with the sort order of their own photos

Should I be passing the photo id, its previous sortorder index and its new sortorder index, retrieve all records between these 2 indices, sort them, then update their orders?

What happens if there are thousands of photos in a single gallery and the sort order is changed?

like image 576
swese44 Avatar asked Jul 24 '11 00:07

swese44


People also ask

How do you sort records in ascending order in Access?

To sort records: Click the Home tab on the Ribbon, and locate the Sort & Filter group. Sort the field by selecting the Ascending or Descending command. The table will now be sorted by the selected field. To save the new sort, click the Save command on the Quick Access Toolbar.

Does indexing improve sorting?

Using the indexes can improve the performance of the sorting operation because the indexes create an ordered structure of the table rows so that the storage engine can fetch the table rows in a pre-ordered manner using the index structure.


2 Answers

What about just using an integer column which defines the order? By default you assign numbers * 1000, like 1000, 2000, 3000.... and if you move 3000 between 1000 and 2000 you change it to 1500. So in most cases you don't need to update the other numbers at all. I use this approach and it works well. You could also use double but then you don't have control about the precision and rounding errors, so rather don't use it.

So the algorithm would look like: say you move B to position after A. First perform select to see the order of the record next to A. If it is at least +2 higher than the order of A then you just set order of B to fit in between. But if it's just +1 higher (there is no space after A), you select the bordering records of B to see how much space is on this side, divide by 2 and then add this value to the order of all the records between A and B. That's it!

(Note that you should use transaction/locking for any algorithm which contains more than a single query, so this applies to this case too. The easiest way is to use InnoDB transaction.)

like image 107
Tomas Avatar answered Oct 05 '22 23:10

Tomas


Store as a linked list, sortorder is a foreign key reference to the next photo_id in the set.

like image 30
Bryan Alves Avatar answered Oct 06 '22 00:10

Bryan Alves