I have a rather unique requirement that I have been trying to solve for weeks now. I have a solution but I don't think it's robust enough.
Problem
I need to generate unique personalized unique labels for items that I upload with a CSV file. These items can grow to billions over time and they expire usually after 60/90 days. So the more records I add over the time I will be erasing them too. Deleting is important because I want to make sure that I give a label with minimum length.
eg. Let's say I need to assign labels to following items.
department = 'A'
items = [ 1 => foo, 2 => bar, 3 => nik, 4 => mik, 5 => baz, 6 => nik, 7 => baz, 8 => baz, 9 => baz, 10 => naz]
department = 'B'
items = [ 1 => foo, 2 => bar, 3 => nik, 4 => mik, 5 => baz, 6 => nik, 7 => baz, 8 => baz, 9 => baz, 10 => naz]
After inserting these records I need the output to be as following.
departments
| id | name |
|---|---|
| 1 | A |
| 2 | B |
items
| id | name | label | segment_value | department_id |
|---|---|---|---|---|
| 1 | foo | foo | 0 | 1 |
| 2 | bar | bar | 0 | 1 |
| 3 | nik | nik | 0 | 1 |
| 4 | mik | mik | 0 | 1 |
| 5 | baz | baz | 0 | 1 |
| 6 | nik | nik1 | 1 | 1 |
| 7 | baz | baz1 | 1 | 1 |
| 8 | baz | baz2 | 2 | 1 |
| 9 | baz | baz3 | 3 | 1 |
| 11 | foo | foo | 0 | 2 |
| 12 | bar | bar | 0 | 2 |
| 13 | nik | nik | 0 | 2 |
| 14 | mik | mik | 0 | 2 |
| 15 | baz | baz | 0 | 2 |
| 16 | nik | nik1 | 1 | 2 |
| 17 | baz | baz1 | 1 | 2 |
| 18 | baz | baz2 | 2 | 2 |
| 19 | baz | baz3 | 3 | 2 |
| 20 | naz | naz | 0 | 2 |
The reason why I want the behaviour is because I need a way to reverse lookup an item with a param like this. A/baz3 should be able to map item 9 on the items table.
Current Solution
Right now I have a trigger which updates the label after inserting the record. I maintain an external counter and for each insert the trigger will use that information to update the label.
Limitations/Current Issues
I am inserting these items 100,000 records or 200,000 records per batch. So I want an efficient insert. Also I want the labels to have a minimum numeric values (It's better if I can reuse baz1 after it's erased in 60 days). Also my current trigger doesn't use a new segment_value for each department_id
CREATE TRIGGER insert_items
BEFORE INSERT ON items
FOR EACH ROW BEGIN
SET NEW.segment_value = ((SELECT IFNULL(MAX(segment_value), 0) from purl_links where segment_key = NEW.segment_key) + 1);
SET NEW.label = CONCAT(NEW.label,NEW.segment_value);
END
I am looking for a decent solution which should help me avoid collision and be able to insert in batch and produce a label with minimum amount of numerics possible (by using available old slots if possible).
PS : I tried to abstract out my problem in the best way possible and I am looking for any help that I can get.