Note that there are some explanatory texts on larger screens.

plurals
  1. POUsing index on inner join table in MySQL
    primarykey
    data
    text
    <p>I have table Foo with 200 million records and table Bar with 1000 records, they are connected many-to-one. There are indexes for columns Foo.someTime and Bar.someField. Also in Bar 900 records have someField of 1, 100 have someField of 2.</p> <p>(1) This query executes immediately: </p> <pre><code>mysql&gt; select * from Foo f inner join Bar b on f.table_id = b.table_id where f.someTime between '2008-08-14' and '2018-08-14' and b.someField = 1 limit 20; ... 20 rows in set (0.00 sec) </code></pre> <p>(2) This one takes just forever (the only change is b.someField = 2):</p> <pre><code>mysql&gt; select * from Foo f inner join Bar b on f.table_id = b.table_id where f.someTime between '2008-08-14' and '2018-08-14' and b.someField = 2 limit 20; </code></pre> <p>(3) But if I drop out where clause on someTime than it also executes immediately:</p> <pre><code>mysql&gt; select * from Foo f inner join Bar b on f.table_id = b.table_id where b.someField = 2 limit 20; ... 20 rows in set (0.00 sec) </code></pre> <p>(4) Also I can speed it up by forcing the index usage:</p> <pre><code>mysql&gt; select * from Foo f inner join Bar b force index(someField) on f.table_id = b.table_id where f.someTime between '2008-08-14' and '2018-08-14' and b.someField = 2 limit 20; ... 20 rows in set (0.00 sec) </code></pre> <p>Here is the explain on query (2) (which takes forever)</p> <pre><code>+----+-------------+-------+--------+-------------------------------+-----------+---------+--------------------------+----------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+--------+-------------------------------+-----------+---------+--------------------------+----------+-------------+ | 1 | SIMPLE | g | range | bar_id,bar_id_2,someTime | someTime | 4 | NULL | 95022220 | Using where | | 1 | SIMPLE | t | eq_ref | PRIMARY,someField,bar_id | PRIMARY | 4 | db.f.bar_id | 1 | Using where | +----+-------------+-------+--------+-------------------------------+-----------+---------+--------------------------+----------+-------------+ </code></pre> <p>Here is the explain on (4) (which has force index)</p> <pre><code>+----+-------------+-------+------+-------------------------------+-----------+---------+--------------------------+----------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+-------------------------------+-----------+---------+--------------------------+----------+-------------+ | 1 | SIMPLE | t | ref | someField | someField | 1 | const | 92 | | | 1 | SIMPLE | g | ref | bar_id,bar_id_2,someTime | bar_id | 4 | db.f.foo_id | 10558024 | Using where | +----+-------------+-------+------+-------------------------------+-----------+---------+--------------------------+----------+-------------+ </code></pre> <p>So the question is how to teach MySQL to use right index? The query is generated by ORM and is not limited to only these two fields. And also it would be nice to avoid changing the query much (though I'm not sure that inner join fits here).</p> <p><strong>UPDATE:</strong></p> <pre><code>mysql&gt; create index index_name on Foo (bar_id, someTime); </code></pre> <p>After that the query (2) executes in 0.00 sec.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload