【问题标题】:Query optimization order by查询优化顺序
【发布时间】:2013-09-27 08:40:34
【问题描述】:

我有两张桌子

  1. Lang 文章 |列:id (INT) ,de (VARCHAR),en (VARCHAR),count_links(INT)
  2. 维基链接 |列:article_id、link_id、nr_in_article(所有整数)

文章名称位于 de(德语)和 en(英语)列中。 LangArticles 表中的 id 与 ids article_id 和 link_id 相同。

我现在想获取链接到另一篇文章的所有文章名称。所以我想要所有链接到“abc”的文章。 'abc' 的 id = '1'

所以我的正常查询(没有顺序)看起来像:

 select distinct(LA.de),W.nr_in_article,LA.count_links from
 LangArticles as LA inner join WikiLinks as W on W.article_id = LA.id
 where W.link_id in ("1") 

这可能需要 0.001 秒并给我 100000 个结果。实际上,我想要最好的 5 次点击。 在这种情况下,最好的意思是最相关的。我想这样排序: 在文章开头链接到'abc'的文章(nr_in_article)并且本身有很多链接(count_links)的文章应该有很高的排名。

我正在使用一个

order by (1-(W.nr_in_article/LA.count_links)) desc 

为此。

问题是我不确定如何优化这个订单。

mysql中的解释说他必须使用临时文件和文件排序,并且不能通过键使用顺序上的索引。为了进行测试,我尝试了 W.nr_in_article 的“简单”订单,因此是一键正常订单。

供您参考,我的索引是:

在LangArticles中:id(主要),de(唯一),en(唯一),count_links(索引)

在维基链接中:article_id(index),link_id(index),nr_in_article(index)

但是我也尝试了这两个多索引 link_id,nr_in_article & article_id,nr_in_article。

使用 order by 的查询大约需要 5.5 秒。 :(

我想我知道为什么 MySql 必须在这里使用临时文件和文件排序,因为必须使用一个索引 (link_id) 找到所有 100,000 个条目,然后必须对其进行排序,并且在临时文件中它不能使用指数。

但是有什么方法可以让这更快吗? 实际上我只想要最好的 5 个命中,所以没有必要对所有内容进行排序。我不确定是否……像坏排序(冒泡排序)这样的排序会比对空洞临时表进行排序的快速排序更快。

【问题讨论】:

  • 既然你只需要前五名,你确实在查询的末尾加上了'LIMIT 5',对吗?不确定 mysql 是否会更快,但您至少应该尝试一下。
  • 顺便说一句,我从未在 distinct(LA.de) 中的一列中看到不同的内容?这是如何表现的!?喜欢group by!?
  • 我试图设置一个限制 5,但我发现它并没有更快,所以我认为 MySql 使用了完整的排序(QuickSort)
  • 好的,这就是我的预期。虽然它很可能不是快速排序,而是合并排序(仅供参考,与手头的问题并不真正相关)。

标签: mysql sql sorting indexing


【解决方案1】:

由于您只需要前 5 个,我认为您可以将其拆分为两个查询,从而减少结果。

首先就像 Sam 指出的那样,

order by (W.nr_in_article/LA.count_links) asc

应该相当于你的

order by (1-(W.nr_in_article/LA.count_links)) desc 

除非我在这里忽略了一些极端情况。

此外,任何地方

W.nr_in_article > LA.count_links

除非结果为空,否则将在前 5 名,所以我会尝试查询

 select distinct(LA.de),W.nr_in_article,LA.count_links
 from LangArticles as LA 
 inner join WikiLinks_2 as W on W.article_id = LA.id
 and W.nr_in_article > LA.count_links
 where W.link_id in ("1")
 order by W.nr_in_article/La.count_links
 limit 5

仅当返回的结果少于 5 个时,您必须使用更改的 where 条件再次进一步执行查询。

然而,这不会将运行时间降低几个数量级,但应该会有所帮助。如果您需要更高的性能,除了物化视图之外我看不到任何其他方式,我认为这在 mysql 中不可用,但可以使用触发器进行模拟。

【讨论】:

  • 我尝试过这种方式,但我想表明相关性更高,所以我使用了 1- 变体。
  • MySQL 视图实际上等同于子查询的连接。最近在 MySQL 5.5 上确认了这一点,所以除了可读性之外它们不会有任何区别。
  • 是的,这就是我谈论物化视图的原因。这些是基于可以索引的视图生成的表,因此 order by 可以使用索引并且速度要快几个数量级。
  • 我确实明白你的意思,只是想补充一下我的发现('事实上' -> '确实',我也来自瑞士:))。
猜你喜欢
  • 2021-07-29
  • 2013-05-26
  • 1970-01-01
  • 2014-02-04
  • 1970-01-01
  • 1970-01-01
  • 2021-11-09
  • 1970-01-01
  • 2012-01-02
相关资源
最近更新 更多