Does the Size of Unselected Columns Impact Performance of SELECT Queries in MySQL?
It depends.
All rows of a table are stored physically on disk in groups known as data pages. By default, a data page is 16 KB big in MySQL. Whenever you query a table, all of the pages that contain the data you ask for, need to be located and loaded off disk. Columns and rows that your query doesn't ask for, may happen to live in the same data page as ones your query does ask for. Obviously loading more data off disk (i.e. a more full data page) will take longer to do. But it's generally rather negligible because 16 KB for a data page is pretty granular. The overhead is fairly small.
The exception to this is for larger rows and columns of data, they're typically stored "off-row", meaning outside the data page that the rest of the row is in. Generally speaking, there's some kind of pointer stored in the page instead that links the two back together. So, when your query requests those data pages, those really large pieces of off-row data don't need to be loaded off disk if your query doesn't ask for them.
Would it be best to move biography and description to a dedicated table to avoid the performance penalty, if any?
Not necessary when they meet the threshold to be stored off-row. That's what the database system is essentially automating for you, at the disk level, as discussed in my previous paragraph.
One use case where storing those larger fields in their own table could improve performance of the workflow in other ways is when it comes to locking with concurrency and DML queries (e.g. UPDATE
s and DELETE
s). If your main table is read from a lot and the large fields are updated equally frequently, you may run into locking contention, since updating a column generally locks that whole row. By separating the larger fields that change frequently into their own table, you eliminate locking against the rest of the row data that's being SELECT
ed against (assuming the SELECT
query isn't utilizing those larger columns in that moment).