【问题标题】:Performance difference in query between cmd and workbench mysqlcmd和workbench mysql之间查询的性能差异
【发布时间】:2020-02-04 13:29:52
【问题描述】:

我有两个问题:

  1. 正如我的标题,对于大量数据运行大型查询,哪一个更有效?

我查看了 MySQL 文档,该文档在 https://www.mysql.com/products/workbench/performance/ 中解释了工作台的性能,但是我似乎找不到任何专门讨论在 cmd 上运行查询和在工作台上查询之间的效率差异的资源。

  1. 如何优化这个查询

    select
      r.user_id,
      k.id as kickscooter_id,
      st_astext(k.location) as location,
      k.created_at,
      k.serial_number,
      k_st.serial_number as states_serial_number,
      st_astext(k_st.gps) as gps_location,
      k_st.gps_updated_at,
      r.start_time,
      r.end_time
    from kickscooters k
    join rents r
      on k.id= r.kickscooter_id
    join kickscooter_states_190614 k_st
      on k.serial_number = k_st.serial_number
    order by r.rent_date
    limit 999;
    

我了解到创建索引可以让 mysql 快速排序,因此我添加了索引

ALTER TABLE `tablename` ADD INDEX `indexname` (`columnname`);

以下来自 SO 帖子 "order by" taking too much time in mysql 之一的答案

按照我已执行的 cmets 中的建议

analyze <my query> 

因为我的服务器是 MariaDB。

这给了我 ERROR CODE 2013: LOST connection to server during query.

我跑的时候

explain <my query>

它工作并输出:

id    select_type   table   type          possible_keys                                                  
1     SIMPLE        k_st    ALL  kickscooter_states_190614_serial_number_date_index             
1     SIMPLE        k       ref  PRIMARY,kickscooters_serial_number_unique,kickscooters_serial_number_index     
1     SIMPLE        r        ref    rents_kickscooter_id_foreign    

-table continued
/       key                       key_len      ref                        rows         extra

        null                        null       null                      192818947      Using temporary; Using filesort
   kickscooters_serial_number_unique 27     kickgoing_db.k_st.serial_number 1   
    rents_kickscooter_id_foreign     4      kickgoing_db.k.id              143  

【问题讨论】:

  • 请先运行EXPLAIN &lt;your select query here&gt;,然后将这个解释计划的结果发布到问题中。
  • 问题是“为什么我的查询很慢”,还是问题“为什么在 CMD 上比在工作台上慢?”。你似乎暗示他们都很慢......
  • @MadhurBhaiya 我已经运行了它,但是它似乎需要一段时间并给了我错误代码:2013:失去连接
  • @NevilleKuyt 我有两个问题,是的,我建议两者都需要很长时间,因此我无法衡量哪个更快,这就是我想问的。
  • @makewhite 请将连接顺序从低基数的表更改为高。然后指定Straight_Join,这样优化器就不会改变连接顺序

标签: mysql database performance indexing


【解决方案1】:

根据解释计划,优化器无法为ORDER BY rent 使用任何索引。所以尝试以下方法:

  1. 确保rents 表的rent_date 列上存在索引。该索引将用于优化ORDER BY 子句。它可以是单列索引,也可以是多列索引(用于其他场景)。但是,如果是多列,则需要确保rent 列是索引顺序中的第一列。
  2. 确保kickscooters 表的id 列上存在索引。关于单列/多列索引的详细信息与第 1 点相同。
  3. 确保kickscooter_states_190614 表的serial_number 列上存在索引。关于单列/多列索引的详细信息与第 1 点相同。

现在,在确保这些索引之后,尝试您的原始查询。最有可能的是,优化器应该能够优化连接顺序。此外,在上述查询中,您可以使用 STRAIGHT_JOIN 优化器提示强制连接顺序。因此,也请尝试以下查询,并在两者之间进行基准测试:

select
  r.user_id,
  k.id as kickscooter_id,
  st_astext(k.location) as location,
  k.created_at,
  k.serial_number,
  k_st.serial_number as states_serial_number,
  st_astext(k_st.gps) as gps_location,
  k_st.gps_updated_at,
  r.start_time,
  r.end_time
from kickscooters k
straight_join rents r
  on k.id= r.kickscooter_id
straight_join kickscooter_states_190614 k_st
  on k.serial_number = k_st.serial_number
order by r.rent_date
limit 999;

【讨论】:

  • 感谢您的帮助。但是,当我从 table_name 运行 show index 时;对于所有表格,它满足所有条件。租金表中的rent_date 是 non_unique 索引,但它的序列是 1 因此满足您的条件。 kickscooters 表中的 id 是主键,kickscooter_states_190614 表上的序列号也是 non_unique,序列为 1。可能是因为rent_date 的基数为 724,与 2M 行相比非常低?
  • @makewhite 请检查您的原始查询和我的回答。我不是要您在rent_date 上编制索引。但我要求您对 rent 列(在您的 ORDER BY 子句中的列)进行索引
  • 对不起,实际上它应该在rent_date分组我在我的查询中写错了我会修复它。
  • @makewhite 请编辑问题并为所有三个表添加SHOW CREATE TABLE &lt;tablename&gt; 的结果;这将给出索引的概念。
  • @MadhurBhaiya - 请告诉我们EXPLAIN,而不是谈论它。
【解决方案2】:

没有WHERE 子句,但有一个ORDER BYLIMIT 涉及r。因此,优化器希望开始r。但是...对于k_st 似乎没有索引serial_number 开头(或者存在类型或排序规则冲突),因此它放弃了r

请为所有 3 张桌子提供SHOW CREATE TABLE

【讨论】: