The database of an online shop on MariaDB: customers, products, orders, order items, reports and customer history
Challenge
The shop database had been designed in a hurry and had nothing but primary keys. With small tables everything was instant, so the missing indexes did not show. As the data grew, queries that used to take milliseconds took hundreds of milliseconds, and lists and reports under load kept the database busy for long moments.
The task: show by measurement what the missing indexes cost on the real data, add the right indexes for the typical queries of a shop, a filter by customer, the order history with a join, a sales report and pagination, and point out the traps that make an index useless even though it was created.
Solution
The database as we found it: four tables, customers, products, orders and order items, with primary keys only. The foreign keys between them existed only in the application code, not as constraints in the database, so nothing had ever created an index on them. For every typical query of the shop we recorded the plan, the number of rows read by a scan and the median time, then added the right indexes one by one and measured the same query again.
The traps got their own measurements: cases in which an index exists and the database does not use it, or uses it badly. And because an index is not a free gain, we measured how much five indexes slow down writes and how much space they take. The shop's data at the time: 100 000 customers, 50 000 products, 500 000 orders and 1.75 million order items on MariaDB 10.11 with InnoDB, as of 2026-10.
Results
- Customer history, a join over three tables
- From 406.8 ms to 0.075 ms
- A customer's orders
- From 500 000 rows scanned to 5
- Look-up by email address
- From 5.9 ms to 0.024 ms
- The ten latest orders
- From 39.3 ms to 0.009 ms
- Sales report by status and date range
- From 34 268 rows to 3 336 with a composite index
- The price of five indexes on the orders table
- Inserts 3.1 times slower, indexes at 237 percent of the table size