【问题标题】:Optimize mysql query (SELECT)?优化mysql查询(SELECT)?
【发布时间】:2012-06-20 12:12:04
【问题描述】:

我有一个包含 300 000 条记录的表 (MyISAM)。我用这个函数从这个表中获取记录:

public function loadRows() {
    if (!$this->result)
        die("Nothing found!");
    $this->rows = array();
    while ($r = mysql_fetch_array($this->result, MYSQL_ASSOC))
        $this->rows[] = $r;
    //mysql_free_result($this->result);
    return $this->rows;
}

显示此表中的 100 条记录的估计时间为 6 秒,非常慢,此查询使用的 MEMORY 为 512 MB。我哪里错了?

查询是:

SELECT i.* FROM inv i 
LEFT JOIN (inv_m im) ON (i.m_id = im.id)
LEFT JOIN (inv_f iff) ON (iff.num = i.num)
LEFT JOIN (temp_a ta) ON (ta.num = i.num)
WHERE i.vid = 1
AND iff.num IS NULL
AND ta.num IS NULL
LIMIT 100

对于 i.vid,我显示所有记录。

声明的索引:

i.m_id 索引

im.id 主键

iff.num 索引

i.num 索引

ta.num 索引

解释结果

id  select_type  table  type     possible_keys  key      key_len  ref                 rows    Extra
1   SIMPLE       i      ref      vid            vid      4        const               85343   Using where
1   SIMPLE       im     eq_ref   PRIMARY        PRIMARY  4        checksys_r1.i.m_id  1 
1   SIMPLE       iff    ref      num            num      182      checksys_r1.i.num   1       Using where
1   SIMPLE       ta     ref      num            num      194      checksys_r1.i.num   1       Using where

【问题讨论】:

  • 您要加入四张桌子,但只谈论一张。发布有关您的架构的更多详细信息。
  • num 字段是否已编入索引?
  • 如果您向inv.numinv_f.numtemp_a.num 列添加索引,您应该会看到速度提高
  • 请显示 EXPLAIN 结果。
  • 所有这些列都是索引

标签: mysql


【解决方案1】:

从跑步开始:

EXPLAIN SELECT i.* FROM inv i 
LEFT JOIN (inv_m im) ON (i.m_id = im.id)
LEFT JOIN (inv_f iff) ON (iff.num = i.num)
LEFT JOIN (temp_a ta) ON (ta.num = i.num)
WHERE i.vid = 1
AND iff.num IS NULL
AND ta.num IS NULL
LIMIT 100

查找诸如全行扫描、文件 i/o 等内容。在此处发布结果。有时桌子可能也需要修理。

另外,您是否有任何理由使用 MyISAM 而不是 InnoDB?

【讨论】:

  • 表 inv、ivm_m 是 myIsam,但表 temp_a 是 innoDB
  • 如果去掉 i.vid = 1(暂时),查询运行速度会快很多吗?
  • 我也不认为 i.vid 有索引。理想情况下,您在 WHERE、HAVING 或 JOIN 子句中使用的任何列都应该被索引。
【解决方案2】:

有 2 个可能的原因,两者都可能起作用。 首先,尽可能避免选择 *。显式指定列将节省您对主数据库的每次连接查询,以便一遍又一遍地查找列名。 第二个是你正在指定一个 where 子句,它只会在你的加入之后运行。所以它将创建一个包含所有连接的庞大记录集,然后过滤该记录集。将您的条件转移到连接本身应该可以让您获得更多的性能提升。 所以.....

SELECT i.Column1, i.Column2, i.Column3 
FROM inv i 
LEFT JOIN (inv_m im) ON (i.m_id = im.id AND i.vid = 1)
LEFT JOIN (inv_f iff) ON (iff.num = i.num AND iff.num IS NULL)
LEFT JOIN (temp_a ta) ON (ta.num = i.num AND ta.num IS NULL)
LIMIT 100

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-24
    • 2021-11-16
    • 1970-01-01
    • 2011-12-15
    • 1970-01-01
    • 2015-07-30
    • 2010-10-30
    相关资源
    最近更新 更多