0

I have an InnoDB table with the following columns

  • id MEDIUMINT UNSIGNED AUTO_INCREMENT
  • a VARBINARY(16)
  • b CHAR(2)
  • c VARCHAR(100)
  • d MEDIUMINT UNSIGNED
  • e TINYINT UNSIGNED, range 0-49

I'll be performing such a query most of the time

SELECT d, e, c FROM tbl WHERE a=0x5caffbb2 AND d>1000000 AND (e=1 OR e=5 OR e=6 OR e=8 OR e=15)

How should I set up indexes for

  1. maximum SELECT speed
  2. decent SELECT speed and high INSERT speed
pedmillon
  • 143
  • 3
  • 13
  • How often are you inserting records? – Kickstart Jul 07 '16 at 09:08
  • very often, sometimes up to 1000x, usually like 50 per second – pedmillon Jul 07 '16 at 13:03
  • The fields you are selecting based on are all ints. So probably worth a covering index on those. Probably worth avoiding indexes on the varchar / char fields. Note that your primary key has a max value of 16777215, which with 50 records inserted per second will over flow in ~93 hours. – Kickstart Jul 07 '16 at 15:36

2 Answers2

1

For the select:

INDEX(a, d)

First column(s), namely a, in index should be compared "= constant".

Then comes one range, namely d > ....

The other stuff is hard to index because of OR. However, it is all the same variable: e=1 OR e=5 OR e=6 OR e=8 OR e=15, which is equivalent to e IN (1, 5, 6, 8, 15). So, this is better:

INDEX(a, e, d)

This is because the optimizer (in 5.6) can "leapfrog" through the index for e. That is, after all the '=' columns, and before the one 'range', you have one 'IN'.

This is a "covering" index:

INDEX(a, e, d, c)

It may be even better. There is a tradeoff between the bulkiness and the "covering". It is not easy to predict whether it will be better; furthermore it may be better for some values and worse for others. This will be 320 bytes versus 20.

(Note: the columns in this index, and the others, must be in the order given.)

more.

For the INSERT

LOAD DATA is probably the best. However if the number of rows in the LOAD are too many, it may have an adverse impact on the SELECTs. Also very good is batched INSERTs of 100-1000 rows per batch.

VARBINARY

That is probably a packed MD5 or IPv6? It may as well be BINARY(16)? It does not hurt the indexing as much as some people say.

InnoDB

Of course, use InnoDB, not MyISAM.

Rick James
  • 135,179
  • 13
  • 127
  • 222
0

Achieve maximum select speed via composites or covered indexes. Problem is, your varchars will get in the way. They (at least one at the moment) are too wide for covered, but your ints are not. So consider choosing a composite index in the most frequently used fashion such as

key (i1,i2,i2) 

for some ints.

For maximum insert speed, choose LOAD DATA INFILE, the hands down fastest approach, even in cases of interactive GUI apps. It takes some configuration of worktables to bring in data. You will need to juggle concepts such as whether or not the data previously existed. And often craft special update with a join pattern solutions for getting the data into the real table from the work table. The fact of the matter is that no looping with binding will achieve this throughput.

Drew
  • 24,851
  • 10
  • 43
  • 78