Do not reinvent the wheel, especially when the one you try to replace is already round.
So let's see how does the existing wheel compare to the one you try to reinvent.
1) Existing wheel (table with columns)
We have a table Entity
which has a structure like this:
id INTEGER PRIMARY KEY
attr1 INTEGER
attr2 REAL -- this holds a date
attr3 TEXT
attr4 TEXT
2) Reinvented wheel, attributes table
Say we'll create a table EntityAttributes
for this that we'll hold all attributes from Entity
at 1), but the question is how shall it look like? Should we use TEXT
as a type for all attribute values and handle the back and forth conversion in the application? Then the table could look like this:
entity_id INTEGER
attr_name TEXT
attr_value TEXT
PRIMARY KEY(entity_id, attr_name)
This is actually not such a big drama since internally Sqlite stores everything as TEXT, but when it comes to any normal RDBMS this is a huge loss.
The alternative is to go for a complex attributes table that supports multiple types. This could look like:
entity_id INTEGER
attr_name TEXT
attr_int INTEGER
attr_real REAL
attr_text TEXT
PRIMARY KEY(entity_id, attr_name)
There is another possibility, to use a master table for the pair (entity_id, entity_name) with a surrogate key and a table for each data type (which has as PK the surrogate key value from the main attributes table), but this is becoming too much for this discussion.
The most important thing to see is that right from the start there are problems we need to workaround when we pick your wheel.
Now let's move on and talk a bit about performance. All values from a row are normally stored next(or close) to each other so IO cost is normally low. That can't be said about multiple rows, especially if they are not inserted one after another. You can always reindex the database file to optimize the access, but it will not help much if the rows are not created one after another.
Another disadvantage of your solution is that it actually need more storage than the natural solution (not by much but still more).
All good till now? How about this: you have the following simple SQL query:
SELECT id, attr1, attr2
FROM Entity
ORDER BY attr1;
Try to do the same by using the attribute per row approach see how easy it is. And this is just an example, many other come to mind.
Compared to traditional RDBMS the attributes table solution looks only worse in your case (for once because they do at better job at keeping the column values of a row together and for another because they support real different types unlike Sqlite).
When using a Key-value data store such as Redis is a different matter.
All in all, there's much to say against the attribute per row approach and really no advantage if you can do the same by using a few columns. The attributes table is useful when you actually need it, something like unknown number of (dynamic) attributes comes to mind but in your case I would stay with the natural solution.