索引和优化

时间:2013-12-09 15:40:02

标签: mysql sql

当谈到超越MySQL的基础知识时,我并不精彩,但是,我正在尝试优化查询:

SELECT DATE_FORMAT(t.completed, '%H') AS hour, t.orderId, t.completed as stamp,
       t.deadline as deadline, t.completedBy as user, p.largeFormat as largeFormat 
    FROM tasks t
    JOIN orders o ON o.id=t.orderId
    JOIN products p ON p.id=o.productId
    WHERE DATE(t.completed) = '2013-09-11'
    AND t.type = 7
    AND t.completedBy IN ('user1', 'user2')
    AND t.suspended = '0'
    AND o.shanleys = 0
    LIMIT 0,100

+----+-------------+-------+--------+----------------------------+-----------+---------+-----------------+-------+-------------+
| id | select_type | table | type   | possible_keys              | key       | key_len | ref             | rows  | Extra       |
+----+-------------+-------+--------+----------------------------+-----------+---------+-----------------+-------+-------------+
|  1 | SIMPLE      | o     | ref    | PRIMARY,productId,shanleys | shanleys  | 2       | const           | 54464 | Using where |
|  1 | SIMPLE      | p     | eq_ref | PRIMARY                    | PRIMARY   | 4       | sfp.o.productId |     1 |             |
|  1 | SIMPLE      | t     | ref    | NewIndex1                  | NewIndex1 | 5       | sfp.o.id        |     6 | Using where |
+----+-------------+-------+--------+----------------------------+-----------+---------+-----------------+-------+-------------+

在添加某些索引之前,它正在p表和o表上执行全表扫描。

基本上,我认为MySQL会:

使用where子句限制tasks表中的行(应该是没有连接的84行)

然后通过orders表到products表获取一个标志(largeFormat)。

我的问题是为什么当MySQL只有84个不同的ID要查找时,为什么MySQL会查找50000多行?有没有办法可以优化查询?

我无法添加新字段或新表格。

提前谢谢!

1 个答案:

答案 0 :(得分:5)

SQL需要处理可用索引以最好地限定查询

我会有一个复合索引 (类型,暂停,完成,完成) 符合您的标准......您的订单和产品表格与现有索引一致。

SELECT 
      DATE_FORMAT(t.completed, '%H') AS hour, 
      t.orderId, 
      t.completed as stamp,
      t.deadline, 
      t.completedBy as user, 
      p.largeFormat as largeFormat 
   FROM 
      tasks t
         JOIN orders o 
            ON t.orderId = o.id
           AND o.shanleys = 0
            JOIN products p 
               ON o.productId = p.id
   WHERE 
          t.type = 7
      AND t.suspended = 0
      AND t.completedBy IN ('user1', 'user2')
      AND t.completed >= '2013-09-11'
      AND t.completed < '2013-09-12'
   LIMIT 
      0,100

我怀疑suspe是一个标志并且是基于数字(int)的,如果是这样,请离开 通过用“0”引号括起来将条件作为数字而不是字符串。

对于日期时间字段,如果您尝试将函数应用于它,则无法使用索引 好吧......所以,如果你只关心一天(或其他查询中的范围), 注意我的日期时间字段&gt; ='2013-09-11'暗示凌晨12:00:00, 并且日期时间字段不到“2013-09-12”,允许在2013-09-11之间的晚上11:59:59 这是整天,指数可以利用它。