【问题标题】:Mysql optimizaiton: is there any way to make this faster?Mysql 优化:有什么方法可以让这更快?
【发布时间】:2015-06-30 10:15:56
【问题描述】:

更新:

感谢所有帮助。我会总结答案。

来自@Jaydee,他的回答成功地将结果减少到 0.09 秒,并且与 LIMIT 中的数字成线性关系。

select * from (select table1.id as table1_id from table1 where table1.id

来自@Rick James,他提到这可能是表 2 的问题。因为我的表 2 只有几列,所以我可以将其省略,并自己进行连接,即使在客户端也是如此!

所以我把表2去掉,只有0.02s!

选择table1.id as table1_id from table1 left join table3table1.table3_id = table3.id 其中table1.id table1.id desc limit 1000 排序;

最后我发现,如果我把table2从inner join改为left join,那么所有的痛苦都消失了,就是0.03s!

table1中选择table1.id作为table1_id左加入table2table1.table2_id = table2.id 左加入table3 table1.table3_id = table3.id 其中table1.id 100000 按table1.id desc limit 1000 排序;

再次感谢您的帮助!

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

注意:我在嵌入式服务器上运行,内存有限(大约 1G,实际上足以放入所有数据,200,000 条数据)并使用 SD 卡作为存储。

select table1.id from table1 where id

(0.01s)

table1中选择table1.id作为table1_id内部连接table2table1.table2_id = table2.id 其中table1.id 100000 order by table1.id desc limit 1000;

(0.40 秒)

table1 中选择table1.id 作为table1_id 内部连接table2table1.table2_id = table2.id 其中table1.id 1000 按table1.id desc limit 1000 排序;

(0.01s)

table1 中选择table1.id 作为table1_id 内部连接table2table1.table2_id = table2.id 左加入table3 table1.table3_id = table3.id 其中table1.id 100000 按table1.id desc limit 1000 排序;

(2.31 秒)

table1 中选择table1.id 作为table1_id 内部连接table2table1.table2_id = table2.id 左加入table3 table1.table3_id = table3.id 其中table1.id 1000 顺序 by table1.id desc limit 1000;

(0.03s)


正如评论所建议的,我使用了解释,但我真的不明白解释说什么。请帮我检查。以下是最长的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                                  |
+----+-------------+----------------------+--------+-------------------------------------------------------------------+---------------------------------------+---------+---------------------------------------------+-------+----------------------------------------------+

来自 desc 表的结果

表1:

+-------------------------+------------------+------+-----+---------------------+----------------+
| 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 |                |
+-------------------------+------------------+------+-----+---------------------+----------------+

表2:

+-----------------+------------------+------+-----+---------------------+----------------+
| 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 |                |
+-----------------+------------------+------+-----+---------------------+----------------+

表3:

+---------------------------+------------------+------+-----+---------------------+----------------+
| 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 |                |
+---------------------------+------------------+------+-----+---------------------+----------------+

【问题讨论】:

  • explain select 对所有慢查询说什么?连接键是否已编入索引?
  • table1.id 上有索引吗?
  • table1.id, table2.id, table3.id 是主键。 table1.table2_id, table1.table3_id 是普通索引(来自 desc table1 的mul)。
  • 显示带有索引的架构(非手工输入)和解释的输出
  • 垃圾进垃圾出你懂钻

标签: mysql database join query-optimization


【解决方案1】:

这表现如何? (糟糕。已更正)

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; 

【讨论】:

  • 是的,这减少到 0.09 秒,并且与 LIMIT 成线性关系。如果我将 LIMIT 减少到 100,现在将是 0.01s。谢谢。
  • 是的,子选择最小化了加入的行数。
【解决方案2】:

看起来 table2 有 1 行。那是对的吗?每张表有多少行?

table2 中只有 1 行,优化器似乎决定从一开始就把它排除在外。

在所有情况下,PRIMARY KEY(id),尤其是在您使用 InnoDB 的情况下,最适合

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

但是,如果大多数表的 id LIMIT)。你用的是什么版本? 5.6 在这方面有一些改进。

请注意,查询有数百万种变体。虽然我感谢您尝试隔离查询的重要部分;您可能会发现将任何答案应用于“真实”查询可能会遇到其他问题。

【讨论】:

  • 谢谢。表 1 目前只有 1 行,但以后会有更多(不会太多),否则表 2 没有意义。根据您的提示,我故意将表 2 移出,它要快得多。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-02
  • 2011-03-01
  • 1970-01-01
  • 2020-03-05
  • 1970-01-01
  • 2022-11-24
相关资源
最近更新 更多