简体   繁体   中英

Mysql optimizaiton: is there any way to make this faster?

Update:

Thanks all the help. I will summarize the answers.

From @Jaydee, his answer successfully reduces the result to 0.09seconds, and it is linear to the number in LIMIT.

select * from (select table1.id as table1_id from table1 where table1.id < 100000 order by table1.id desc limit 1000) t1 inner join table2 on t1.table2_id = table2.id left join table3 on t1.table3_id = table3.id order by t1.id;

From @Rick James, he mentions that it might be problem of Table 2. Because my table 2 only has several columns, I can leave it out, and do the join myself, even at client side!

So I remove table 2, and it is only 0.02s!

select table1 . id as table1_id from table1 left join table3 on table1 . table3_id = table3 . id where table1 . id < 100000 order by table1 . id desc limit 1000;

At last, I found that, if I change table2 from inner join to left join, then all the pains goes away, it is 0.03s!

select table1 . id as table1_id from table1 left join table2 on table1 . table2_id = table2 . id left join table3 on table1 . table3_id = table3 . id where table1 . id < 100000 order by table1 . id desc limit 1000;

Thanks again for the help!

==============================

Note: I am running on embedded server with limited ram (about 1G, enough to put in all data actually, 200,000 data) and using SD card as storage.

select table1.id from table1 where id<100000 order by id desc limit 1000;

(0.01s)

select table1 . id as table1_id from table1 inner join table2 on table1 . table2_id = table2 . id where table1 . id < 100000 order by table1 . id desc limit 1000;

(0.40s)

select table1 . id as table1_id from table1 inner join table2 on table1 . table2_id = table2 . id where table1 . id < 1000 order by table1 . id desc limit 1000;

(0.01s)

select table1 . id as table1_id from table1 inner join table2 on table1 . table2_id = table2 . id left join table3 on table1 . table3_id = table3 . id where table1 . id < 100000 order by table1 . id desc limit 1000;

(2.31s)

select table1 . id as table1_id from table1 inner join table2 on table1 . table2_id = table2 . id left join table3 on table1 . table3_id = table3 . id where table1 . id < 1000 order by table1 . id desc limit 1000;

(0.03s)


As the comment suggested, I used explain, but I don't really understand what does explain say. Please help me check. The following is the longest 2.31s.

+----+-------------+----------------------+--------+-------------------------------------------------------------------+---------------------------------------+---------+---------------------------------------------+-------+----------------------------------------------+
| id | select_type | table                | type   | possible_keys                                                     | key                                   | key_len | ref                                         | rows  | Extra                                        |
+----+-------------+----------------------+--------+-------------------------------------------------------------------+---------------------------------------+---------+---------------------------------------------+-------+----------------------------------------------+
|  1 | SIMPLE      | table2               | index  | PRIMARY,table2_id_index                                           | table1_id_index                       | 4       | NULL                                        |     1 | Using index; Using temporary; Using filesort |
|  1 | SIMPLE      | table1               | ref    | PRIMARY,table1_table2_id_foreign,table1_id_index                  | table1_table2_id_foreign              | 4       | videocap.table2.id                          | 27222 | Using where                                  |
|  1 | SIMPLE      | table3               | eq_ref | PRIMARY                                                           | PRIMARY                               | 4       | videocap.table1.table3_id                   |     1 | Using index                                  |
+----+-------------+----------------------+--------+-------------------------------------------------------------------+---------------------------------------+---------+---------------------------------------------+-------+----------------------------------------------+

results from desc table

table1:

+-------------------------+------------------+------+-----+---------------------+----------------+
| Field                   | Type             | Null | Key | Default             | Extra          |
+-------------------------+------------------+------+-----+---------------------+----------------+
| id                      | int(10) unsigned | NO   | PRI | NULL                | auto_increment |
| table2_id      | int(10) unsigned | NO   | MUL | NULL                |                |
| table3_id | int(10) unsigned | NO   | MUL | 0                   |                |
| created_at              | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
| updated_at              | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
+-------------------------+------------------+------+-----+---------------------+----------------+

table2:

+-----------------+------------------+------+-----+---------------------+----------------+
| Field           | Type             | Null | Key | Default             | Extra          |
+-----------------+------------------+------+-----+---------------------+----------------+
| id              | int(10) unsigned | NO   | PRI | NULL                | auto_increment |
| created_at      | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
| updated_at      | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
+-----------------+------------------+------+-----+---------------------+----------------+

table3:

+---------------------------+------------------+------+-----+---------------------+----------------+
| Field                     | Type             | Null | Key | Default             | Extra          |
+---------------------------+------------------+------+-----+---------------------+----------------+
| id                        | int(10) unsigned | NO   | PRI | NULL                | auto_increment |
| created_at                | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
| updated_at                | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
+---------------------------+------------------+------+-----+---------------------+----------------+

How does this perform? (Ooops. Corrected)

select  *
    from  
      ( SELECT  table1.id as table1_id
            from  table1
            where  table1.id < 100000
            order by  table1.id desc
            limit  1000
      ) t1
    inner join  table2 on t1.table2_id = table2.id
    left join   table3 on t1.table3_id = table3.id
    order by  t1.id; 

It looks like table2 has 1 row. Is that correct? How many rows in each table?

With only 1 row in table2, the optimizer seemed to decide to get it out of the way to start with.

In all cases, PRIMARY KEY(id) , especially if you are using InnoDB, is optimal for

    where     table1.id < $number
    order by  table1.id desc

However, if most of the table has id < 100000, then the optimizer may (erroneously) decide to do a table scan (because it did not take into account the LIMIT ). What version are you using? 5.6 has some improvements in this area.

Keep in mind that there are millions of variations on queries. While I appreciate your attempt to isolate the important parts of the query; you may find that applying any answer back to the 'real' query may hit some other hiccup.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM