【问题标题】:Simple: What makes this query inefficent?简单:是什么让这个查询效率低下?
【发布时间】:2012-06-18 22:09:02
【问题描述】:
SELECT 
    t1.`id` , 
    t1.`some_key` ,  
    t1.`date` ,
    t2.`data`
FROM `table1` AS `t1`
    LEFT JOIN `table2` AS `t2` ON t2.`id` = t1.`some_key`
WHERE DATE( t1.`date` ) = DATE( NOW( ) )

我正在尝试搜索 table1 中今天添加的所有记录。我不知道记录的数量。我尝试在日期列中添加一个索引,但是我的 EXPLAIN 仍然显示 MySQL 搜索 table1 中的所有 n 多行。

EDIT::: 按要求解释

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra 
1   PRIMARY     <derived2>  ALL     NULL    NULL    NULL    NULL    4   
1   PRIMARY     t2  eq_ref  PRIMARY     PRIMARY     4   t1.some_key     1   
2   DERIVED     table2  ALL     indx    NULL    NULL    NULL    5   Using where

【问题讨论】:

  • date 上有索引吗?即使有,在桌子上不使用date() 函数并使用&gt; 会更有效。 WHERE t1.date &gt; DATE(NOW())
  • 我的 0.02:鉴于您转换索引数据的事实,没有办法事先知道结果。结果:全扫描
  • 索引或没有索引它仍然会进行全面扫描。你会怎么做呢?

标签: mysql join indexing


【解决方案1】:

您正在 t1.date 进行转换;您失去了索引的好处,因为现在您的查询需要查看每一列。 t1.date 可以被索引,但 DATE( t1.date ) 不是。

【讨论】:

  • 我尝试将其设置为 internval + 0 秒,但它仍然会扫描所有行
  • 你明白了。不要转换日期列,而是搜索 t1.date >= DATE(NOW()) AND t1.date
【解决方案2】:

尝试重构查询

SELECT 
    t1.`id` , 
    t1.`some_key` ,  
    t1.`date` ,
    t2.`data`
FROM 
    (
        SELECT * FROM `table1`
        WHERE `date` >= (DATE(NOW()) + INTERVAL 0 SECOND)
    ) AS `t1`
    LEFT JOIN `table2` AS `t2`
    ON t2.`id` = t1.`some_key`
;

表达式(DATE(NOW()) + INTERVAL 0 SECOND) 是今天午夜

mysql> select (DATE(NOW()) + INTERVAL 0 SECOND);
+-----------------------------------+
| (DATE(NOW()) + INTERVAL 0 SECOND) |
+-----------------------------------+
| 2012-06-15 00:00:00               |
+-----------------------------------+
1 row in set (0.00 sec)

mysql>

这是第二次尝试

SELECT 
    t1.`id` , 
    t1.`some_key` ,  
    t1.`date` ,
    t2.`data`
FROM 
    (
        SELECT id,somekey FROM `table1`
        WHERE `date` >= (DATE(NOW()) + INTERVAL 0 SECOND)
    ) AS t1
    INNER JOIN `table2` AS `t2` ON t1.`some_key` = t2.`id`;
;

请确保 table1 有一个 (date,id,somekey) 索引

ALTER TABLE table1 ADD INDEX date_id_somekey_index (`date`,id,somekey);

子查询是对索引的纯范围扫描,没有表访问!!!

我还将 LEFT JOIN 更改为 INNER JOIN。

至少要调查子查询单独运行它:

SELECT id,somekey FROM `table1`
WHERE `date` >= (DATE(NOW()) + INTERVAL 0 SECOND);

这个子查询只会为 t1 生成今天的条目

【讨论】:

  • 由于将其设为子查询的额外开销,这实际上会使其运行更慢(甚至几微秒)。这不会提高相关查询的性能。加上返回所有内容(*)并没有帮助;)
  • 是的,它仍然扫描了派生表 1 上的所有行
  • 请创建建议的索引并在我的第二个查询中运行 EXPLAIN 计划并将输出发布到您的问题中。
  • 谢谢:)。顺便说一句,table1 中有 5 行。只有 4 个有今天的日期
  • 请运行我的第二个查询,如果它运行得快,请告诉我
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-04
  • 1970-01-01
  • 1970-01-01
  • 2020-06-16
相关资源
最近更新 更多