当前位置: 首页 > 面试题库 >

MySQL查询优化-加入?

赵飞雨
2023-03-14
问题内容

一个供您所有MySQL专家使用的技巧:-)

我有以下查询:

SELECT o.*, p.name, p.amount, p.quantity 
FROM orders o, products p 
WHERE o.id = p.order_id AND o.total != '0.00' AND DATE(o.timestamp) BETWEEN '2012-01-01' AND '2012-01-31' 
ORDER BY o.timestamp ASC
  • 订单表= 80,900行
  • 产品表= 125,389行
  • o.id和p.order_id已建立索引

该查询大约需要6秒钟才能完成-太长了。我正在寻找一种优化它的方法,可能使用临时表或其他类型的联接。恐怕我对这两个概念的理解还很有限。

谁能建议我优化此查询的方法?


问题答案:

首先,我将使用其他样式的语法。
ANSI-92已经有20年的睡眠时间了,许多RDBMS实际上建议不要使用您曾经使用的符号。在这种情况下,这不会有所作为,但是出于多种原因,这确实是一个很好的做法
(我会让您调查一下并自己做出决定)

最终答案和示例语法:

SELECT
  o.*, p.name, p.amount, p.quantity  
FROM
  orders
INNER JOIN
  products
    ON orders.id = products.order_id 
WHERE
      orders.timestamp >= '2012-01-01'
  AND orders.timestamp <  '2012-02-01'
  AND orders.total     != '0.00' 
ORDER BY
  orders.timestamp ASC

由于该orders表是您进行初始过滤时使用的表,因此这是一个开始进行优化的好地方。

DATE(o.timestamp) BETWEEN x AND y您一起成功获取一月份的所有日期和时间。但这需要在表中的
每一行
DATE()上调用函数 (类似于RBAR的含义) 。RDBMS无法 看透 此功能, 只是知道
如何避免浪费时间。相反,我们需要进行优化,方法是重新排列数学,以使我们不需要要过滤的字段上的函数。 __orders __

    orders.timestamp >= '2012-01-01'
AND orders.timestamp <  '2012-02-01'

此版本使优化程序可以 知道
您想要一组彼此连续的日期。这称为范围搜寻。它可以使用索引非常快速地找到适合该范围的第一个记录和最后一个记录,然后挑选出介于两者之间的每条记录。这样就避免了检查所有不适合的记录,甚至避免了检查范围中间的所有记录。只需要寻找边界。

假定所有记录按日期排序,并且优化器可以看到该记录。为此,您需要一个索引。考虑到这一点,似乎有两个基本覆盖索引,你可以使用:
- (id, timestamp)
-(timestamp, id)

首先是我看到人们使用最多的东西。但这迫使优化器分别timestamp对每个对象进行范围搜索id。而且由于每种id可能性都有不同的timestamp价值,因此您一无所获。

第二个索引是我推荐的。

现在,优化器可以非常快地完成查询的这一部分。

SELECT
  o.*
FROM
  orders
WHERE
      orders.timestamp >= '2012-01-01'
  AND orders.timestamp <  '2012-02-01'
ORDER BY
  orders.timestamp ASC

碰巧的是,即使ORDER BY使用建议的索引进行了优化。您已经按照想要输出数据的顺序进行了操作。加入后无需重新排序所有内容。

然后,为了满足total != '0.00'要求,仍会检查范围内的每一行。但是您已经将范围缩小得太多,以至于这可能很好。
(我不会去到它,但你可能会发现它无法使用索引在MySQL优化该 timestamp范围寻道)。

然后,您就加入了。这已经通过您已有的索引进行了优化(products.order_id)。对于上面摘录中选择的每条记录,优化器都可以进行索引查找并非常快速地识别出匹配的记录。

所有这些都假定在绝大多数情况下,每个订单行都有一个或多个产品行。例如,如果只有极少数几个订单具有任何产品行,则首先选择感兴趣的产品行可能会更快;本质上看是以相反顺序发生的联接。

优化器实际上是为您做出决定的,但是要知道这样做是很方便的,然后提供您估计对它最有用的索引。

您可以检查说明计划,以查看是否正在使用索引。如果不是,您的帮助尝试将被忽略。可能是因为数据的统计数据暗示了连接的不同顺序更好。如果是这样,则可以提供索引来代替该连接顺序。



 类似资料:
  • 问题内容: 这就是整个查询… 如果… 和… 有明显的理由吗? 正在服用? 扩展说明 问题答案: 您可以始终使用EXPLAIN或EXPLAIN EXTENDED 来查看MySql对查询所做的操作 您也可以用稍微不同的方式编写查询,是否尝试过以下方法? 看看效果如何会很有趣。我希望它会更快,因为目前,我认为MySql将为您拥有的每个节目运行内部查询1(这样一个查询将运行多次。联接应该更有效。) 如果希

  • 主要内容:概述,一、关联查询优化,1.左(右)外连接,2.内连接,3.JOIN语句原理,4.JOIN小结,5.Hash Join,二、子查询优化,三、排序优化,四、GROUP BY优化,五、优先考虑覆盖索引,六、使用前缀索引,七、索引下推ICP,八、其他查询优化,1.COUNT(*)与COUNT(具体字段)效率,2.不使用SELECT *,3.LIMIT 1优化,4.多使用commit概述 数据库调优的方式有多种: 建立索引、充分利用到索引、不让索引失效 对SQL语句进行优化 调优如缓冲、线程数

  • 本文向大家介绍Mysql慢查询优化方法及优化原则,包括了Mysql慢查询优化方法及优化原则的使用技巧和注意事项,需要的朋友参考一下 1、日期大小的比较,传到xml中的日期格式要符合'yyyy-MM-dd',这样才能走索引,如:'yyyy'改为'yyyy-MM-dd','yyyy-MM'改为'yyyy-MM-dd'【这样MYSQL会转换为日期类型】 2、条件语句中无论是等于、还是大于小于,WHERE

  • 本文向大家介绍Mysql查询语句优化技巧,包括了Mysql查询语句优化技巧的使用技巧和注意事项,需要的朋友参考一下 索引优化,查询优化,查询缓存,服务器设置优化,操作系统和硬件优化,应用层面优化(web服务器,缓存)等等。这里的记录的优化技巧更适用于开发人员,都是从网络上收集和自己整理的,主要是查询语句上面的优化,其它层面的优化技巧在此不做记录。 查询的开销指标: 执行时间 检查的行数 返回的行数

  • 我有一个需要50秒的查询 security_tasks中的记录=841321 relations中的记录=234254 我能做些什么让它快一点,比如快1秒或2秒 有什么想法吗?

  • 本文向大家介绍Mysql优化技巧之Limit查询的优化分析,包括了Mysql优化技巧之Limit查询的优化分析的使用技巧和注意事项,需要的朋友参考一下 前言 在实际业务中对于分页来说是一个比较常见的业务需求。那么就会使用到limit查询,当我们在使用Limit查询的时候,在数据比较小、或者只查询前面一部分数据的时候效率是很高的。但是当数据量大的时候,或者查询offset数量比较大的时候,如:lim