【问题标题】:mysql slow performance on a small table with join querymysql 在带有连接查询的小表上性能缓慢
【发布时间】:2011-10-07 08:29:49
【问题描述】:

当我执行以下查询时,我有几个表连接在一起:

SELECT article.year, authors.last_name, count(DISTINCT article.id) as count FROM
article LEFT JOIN authors ON article.id = authors.id WHERE authors.last_name =
'bloggs' GROUP BY article.year

由于某种原因,这需要 6 到 7 秒才能返回结果,考虑到它必须处理的行数相对较少,这对我来说似乎慢得令人难以置信。我在这里做错了吗?

如果我在查询上运行 EXPLAIN,我会得到以下信息:

select_type    table    type   possible_keys  key    key_len    ref    rows    extra
=====================================================================================
simple         article  all    null           null    null      null   762     using temporary; using filesort
simple         authors  all    null           null    null      null   5061    using where; using join buffer

两个表都是 InnoDB。我是从我的本地机器上运行的,它的规格相当低(windows xp,1 ghz,1gb ram),但即便如此,我认为这会更快。如果我将更多行加载到表中,它开始需要几分钟而不是几秒钟。

有什么想法吗?

下面的表结构:

Article:

field    type       null    key    default    extra
=======================================================
id       int        yes            null
year     char(20)   yes            null
volume   char(20)   yes            null
issue    char(20)   yes            null
title    text       yes            null

Authors:

field      type       null    key    default    extra
=======================================================
id         int        yes            null
last_name  char(100)  yes            null
initials   char(10)   yes            null

【问题讨论】:

  • 你有authors.last_name的索引吗?您对用于连接的列有索引吗?你有authors.last_name 的索引吗?如果您根本没有索引,那么随着表大小的增长,它会越来越慢。
  • 也发布你的表格结构。 (我的意思是authors.last_namearticle.year。)
  • 不,目前我在查询中使用的列上没有任何索引,这很好。我没有添加它们,因为在这个阶段它似乎是一个相当小的表来处理,但我会尝试在受影响的列上添加索引,看看它是否能解决任何问题......
  • 您还应该考虑将year 设为INT 而不是char(20)。它是 4 个字节(如果您将其设为 SMALLINT,则为 2 个字节)而不是 20 个。更少的空间,更少的索引空间,没有人可以使用year='my gosh, 2012' 添加一行。

标签: mysql performance left-join


【解决方案1】:

尝试在 authors.last_nameauthors.id 列上添加索引。

但是,您确定您的查询没问题吗?不应该是这样吗:

SELECT article.year, authors.last_name, count(DISTINCT article.id) as count FROM
article LEFT JOIN authors ON article.author_id = authors.id WHERE authors.last_name =
'bloggs' GROUP BY article.year

如果是这样,则需要在 articles.author_id 上建立索引 - 虽然不是针对此查询,但作为一般最佳实践

【讨论】:

  • 正如@Tudor 所提到的,您需要一个article.author_id 字段,即FOREIGN KEYauthor(id)。您还需要声明哪个字段是PRIMARY KEY(在两个表中),并进一步索引WHEREON 中使用的任何其他字段。
  • 谢谢大家,我会玩一玩,让你知道结果。
  • 只是为了让大家知道我在相关列上添加了索引并且它产生了巨大的差异,所以谢谢你。一开始没做感觉有点傻,我只是没想到它在这么小的桌子上如此重要。
【解决方案2】:

正如 Tudor 所说,添加索引。您还可以提取分组依据。

SELECT * FROM (SELECT article.year, authors.last_name, count(DISTINCT article.id) as count FROM
article LEFT JOIN authors ON article.author_id = authors.id WHERE authors.last_name =
'bloggs') GROUP BY article.year

这样做你首先通过连接获取,然后在集合中应用聚合函数。

explain 看看哪里有改进的地方。

建议的字体:

http://kccoder.com/mysql/join-group-by-performance/

【讨论】:

  • 为什么你认为这种改变会有所帮助?
  • 你链接的例子只有一个表 - 和GROUP BY - 在子查询中和JOIN 在外部查询中。你把它倒过来了。
猜你喜欢
  • 2023-03-12
  • 2016-03-09
  • 2022-01-02
  • 1970-01-01
  • 2022-10-01
  • 2016-05-10
  • 2019-08-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多