2015-05-01 30 views
1

任何人都可以帮助我理解为什么运行这两个查询所花费的时间似乎有如此巨大的差异。我正在使用水豚遍历页面的报表部分上的所有锚定标记,然后将每个值放入数组中,以便我可以检查值。查询执行说明差别很大

@links = page.all('table.report > tbody > tr > .col_7 > a') 
@links.map(&:text) # This takes approx 20 seconds to go through 239 results 
@links.map { |l| l['title'] } # This takes about 3 seconds 

为什么会有这么大的差异?我期待了解地图功能的每个变体之间的主要区别。

感谢

+0

你有没有尝试与'@links.map {| l | l.text}'?我认为它更多的是关于不同类型的DOM扫描,而不是关于不同的“地图功能变化”。 – PSkocik

+1

我的意思是,标题只是一个标签属性 - 它应该已经存储在链接对象实例中。 '#text'可能是一种递归扫描所有子节点并提取其文本内容的方法。 – PSkocik

+0

谢谢,现在我明白了一点吧 – Richlewis

回答

2

这应该是关于您必须为每个DOM扫描执行的类型,而不是关于不同的“地图功能变化”。 大概,标题只是一个标签属性,当您尝试使用#[]()检索对象时,该对象实例已存储在link对象实例中,而#text很可能是递归扫描每个链接的子节点的方法,而从每个中提取文本。

#map(&:text)#map {|item| item.text },实际上不是两个“地图功能的变体”。他们是完全相同的版本。什么一元&确实到非PROC对象不是一个块是:

  1. 它调用#to_proc在其上,其中在码元的情况下:symbol将产生的Proc.new {|item| item.symbol }
  2. 等效它转换PROC在第一步中的块,其中在码元的情况下:symbol将产生的{|item| item.symbol}

(等效获取参见一元&部分中http://ablogaboutcode.com/2012/01/04/the-ampersand-operator-in-ruby/

因此,就#map而言,当您执行@links.map(&:text)时,它被调用@links.map { |item| item.text }

1
@links.map(&:text) 

当调用一个ActiveRecord ::关系映射,数据库被击中,所有的@link(S)是通过调用返回(但不处理)

(&:文本),但是,每个对象必须构造,然后,叫上他们每个人的文字()方法

@links.map { |l| l['title'] } 

虽然我不能肯定,我相信一个查询优化器可以很容易地将其修改为:@link.pluck(:title),这将导致一个数据库命中,因此会返回所有链接标题(显然比构建每个查询更快)即使情况并非如此,我们只需从对象中提取属性:标题而不需要构造它

+0

感谢您的回答,即时消息不使用数据库在这种情况下,但我看到你在说什么 – Richlewis

+0

@link不是一个ActiveRecord :: Base –