Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Cerbix's avatar

Too many Columns / Fields in Table, ideas on how to resolve?

TLDR: My table has hundreds of columns. (Why explained below) skip to my question on how to combine multiple tables to act as 1.

So on my site I have a settings page where users enable and create specific connections to features on my site, and then enable/disable specific settings for each of the connections. They do this by inputting their unique id's for each connection, and then choosing which settings they want to use for each.

All of the "connections" are then passed through a resource json API, and the data is consumed with code elsewhere.

So I have a "connections" table that looks something like this:


id
user_id

connection1_id
connection1_settings1
connection1_settings2
connection1_settings3

connection2_id
connection2_settings1
connection2_settings2
connection2_settings3

3. 4. etc...

Then it uses a Model and Eloquent belongsTo to tie each one to a user.

Which was fine when I originally created it, because I only had a few connections and the table was quite small and seemed to fall within database normalization rules as all of the data is unique to each user, it's never duplicated and it's all related.

But my site has recently became quite popular, and many open source projects have asked to be added as a unique connection/option.

So this Table has grown from about a dozen columns, to over 200 columns. At about 120 Columns I started getting table size errors when migrating/adding new fields, but was able to temporarily resolve this by changing all the "settings" fields to tinyInteger's instead of strings, saving some space.

So my question:

Inevitably this table is going to get too large, with too many columns/fields. So to be proactive and resolve this before it grows into a bigger problem, what do you guys think would be the best way to split the future growth into multiple tables, and interlink them all into the one json?

I have used Pivot tables before to help spread out fields across multiple tables and keep things cleaner. But since the site already has thousands of users/rows in the original table, unless I'm mistaken it seems each time I add a new connection option. (Say Connection100_id, 200, 500, whatever.) I would have to "attach" each of those new options to the thousands of rows/users in the original table manually, for them to all link together with the existing table. (to prevent a bunch of "cannot find connection200_id" errors, etc.)

Is there any way to use Eloquent and a model to effectively continue expanding this into multiple tables without creating too much back end work to consume it? (I want it to act as much like a single table as possible.)

Thanks for any help/advice.

0 likes
9 replies
Martal's avatar

If you do not every piece of data in every case, you could divide record in several tables and make 1-to-1 relationship between them. And add default eager load to it.

Cerbix's avatar

Thanks for the tips, I'll do some research and test it out.

itsfg's avatar

Why not have :


id
user_id

connection_number //your 1, 2, 3 ...
connection_settings1
connection_settings2
connection_settings3

And if a user uses 2 connections you have 2 rows associated to this user ?

You may have maybe different number of settings for each connection, so maybe some fields will remain always null.

Maybe it's not a problem.

Maybe it is, then @martal solution is great.

And you could also do a polymorphic relationship between the users and the many different connections to get a normalized collection of all connections of a user.

Snapey's avatar

Create a table with each row containing

connection_id
connection_settings1
connection_settings2
connection_settings3

etc

Tray2's avatar
Tray2
Best Answer
Level 73

I would take it even one step further than @snapey's suggestion and have these fields in my table

  • connection_id
  • setting
  • setting_type

and use a one to many relationship.

Cerbix's avatar

I like the idea the three of you had about putting each connection on a different row, and defining which they belong to with a one to many relationship.

Basically making it infinitely scalable while only using a few columns in a single table.

This would require a complete restructure of my controllers, which I don't think would be too bad. But the worst part being, it would require me to manually move each field of my production database table over to the new table type.

Or require all my users to re-setup the connections on their accounts.

Both could be quite messy. I'll think it over.

Tray2's avatar

It's quite easy to do with a few SQL commands

Something like

insert into sometable (connection_id, setting, type)values (select connection_id, connection_settings1, 1);

And then do the same thing for setting 2 and 3,

Cerbix's avatar

My solution thanks to your help:

I ended up using a few of your guys advice. Going with two tables, (connections and connection_settings) and using the "one to many" relationship (hasMany and belongsTo). Using the original "connections" table to house the hasMany relationship, and a few server settings fields.

Then using the second "settings" table to house all of the individual connection types and their independent settings. Reducing it down from over a hundred columns before, to just a few, and then identifying them individually with a connection_type value. (Each one using a different row, instead of a different column.)

I then pass the connections and connection_settings queries from my controller into a Resource Collection, and using a bunch of foreach and isset statements sort through them all, and combined them all into a single collection which exactly replicates my original api json output. (So that I do not have to modify any of my code which consumes the api data.)

I also set it up so that if a user does not need to enable any specific connection types, instead of writing null fields to the table like before, it just doesn't add it to the database at all (so that it does not waste any unneeded rows). Instead using my resource collection to just pass in faux null fields for any connection type that the user doesn't need. (This is just to prevent any front end errors from missing variables not existing at all.)

I do have one question though:

I figured out my "store" function, just cycle through the inputs with a foreach, if isset pass to database.

But what's the best solution to edit/update my settings fields when using a hasMany relationship. For instance each user will now have a single connection with dozens of connection_settings. (one to many)

When a user uses the update function in the dashboard do I just delete all of them and re-write them over again to the database?

Or is there some simpler method that won't require me to query each "connection_type" individually by their value and id and then pass in the updated values? (This sounds like it'd take a lot of lines and queries to accomplish compared to the delete and re-write method. Maybe I'm just overthinking this though? And eloquent has some magical feature to get this done I'm not aware of?)

Please or to participate in this conversation.