There are maybe several hundred writes a day, versus the tens of thousands of reads. My databases are located on an SSD drive.
Based on this statement, let's play with some numbers. Lets's say there are 500 writes a day and 20,000 reads a day. That computes out to the following
- 97.56% reads per day
- 2.44% writes per day
- 40 reads / write
As much as I love InnoDB, I would have to choose MyISAM in this case for several reasons
REASON #1
You only have 150MiB of MyISAM tables (70MiB Data, 80 MiB Indexes)
REASON #2
InnoDB indexes tend to get very bloaty because Secondary Indexes have keys into the Clustered Index. This always results in a double index lookup. This can be overlooked with large, write-heavy datasets.
REASON #3
InnoDB tablespaces tend to get very bloaty because of MVCC being created and discarded without an automatic reclaiming of disk space:
All this can be avoid with MyISAM
REASON #4
InnoDB protects individual rows by performing MVCC for transaction control. The overhead generated for reads in a day would probably be greater than 150 MiB.
I can probably name 2 or 3 more reasons, but let's cut to the chase: Is there anything that can improve performance for MyISAM in your case? Why, yes there is.
Your said the following
The table is about 260k rows in size, with 28 fields which for the most part is varchars and ints
If you have many varchars, there is something you can do to increase read/write performance. For any MyISAM table mydb.mytable
: run this command:
ALTER TABLE mydb.mytable ROW_FORMAT=Fixed;
What will this do, this will treat all VARCHARs as CHARs. Every row will be the exact same length. This will increase disk space 80%-100%. In your case, let's assume it doubles your 150 MiB MyISAM table to 300 MiB. Where is the benefit? Your MyISAM table can now be read/written anywhere from 20% - 30% faster without changing anything else I learned that from pages 72,73 from MySQL Database Design and Tuning.
I have written about this in the past:
Making one large table would be a mistake: you'll have a table with lots of NULL values and it would soon evolve into a maintenance nightmare. And about saving the data as XML or JSON -- (slaps your wrist) that's for even considering it.
Every Resulttype should get its own table, each of these tables has a primary key over an ID column and (this is the trick!) all of these IDs are taken from the same sequence!
Then you only need a table with the columns projectid, resultid (and optionally resulttype). Since you will look for the primary key, even searching over all tables can be done fast.
Best Answer
Since Consumers and Merchants share some common data as Users they should be in a single base table, as you have already mentioned.
An EAV implementation can be successful under some well planned and controlled use. But I see nothing in your question that would imply that an EAV solution is the right answer.
In fact, as you move further in your development you might find that not only do Merchants have some additional attributes, but so do Consumers. If so, you might want a simple Supertype-Subtype model.
That would give you 3 tables that are related as shown below:
If this works for you, much of the time you would only access the Users table, but when you needed additional information for a Consumer or a Merchant you would like to those details as well.
This is a pretty simple approach and avoids unneeded duplication of data.
For a perspective on EAV implementations, you might look at Aaron Bertrand's post, which explains the advantages and the limitations.
Note that in this case it was rapidly changing requirements which made the EAV decision a good choice.