我对这种代码采取了行动:
Timesheet::WorkPeriod.includes(:ship).limit(2000).to_a
render nothing: true
服务器答案给出:
method=GET path=/timesheet_reports/rest_hours format=html controller=Company::Timesheet::ReportsController action=rest_hours status=200 duration=2106.43 view=3.68 db=23.75
但是,在浏览器中,渲染需要6秒(对于空白)页面。如果我将2000
更改为更高的值,则会有4秒的差异。
如果我删除了includes
或to_a
,这是正确的。如果我这样做的话也一样:
Timesheet::WorkPeriod.includes(:ship).limit(2000).each(&:id)
即使存在n + 1个查询问题,删除包含也是最快的。
我使用的是ruby 2.3和Rails 4.2。
我认为内存分配存在问题,但我不知道如何解决它。我该怎么办?
答案 0 :(得分:0)
为什么使用包含? SQL看起来像什么? 也许如果您阅读sql,您会看到:
Timesheet::WorkPeriod.includes(:ship)
# SELECT "work_period".* FROM "work_period"
# SELECT "ship".* FROM "ship" WHERE "ship"."work_period_id" IN (....)
如果您有很多行,查询的成本可能很高!
另外因为你的结果可能很大。操作ruby中的巨大阵列需要花费。
在使用ruby之前,尽量使用尽可能多的活动记录方法,例如:
Timesheet::WorkPeriod.includes(:ship).limit(2000).each(&:id)
# use select if you need AR object
Timesheet::WorkPeriod.includes(:ship).limit(2000).select(:id)
# or pluck if you need the list of value in column
Timesheet::WorkPeriod.includes(:ship).limit(2000).pluck(:id)
当您访问页面时,还要检查日志,看看您是否没有N + 1。宝石bullet也可以帮助你。 如果它没有帮助你。使用rack-mini-profiler。
进一步阅读:
答案 1 :(得分:0)
确保您的关系已编入索引。而且,使用pluck而不是每个。
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="line">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="sequence"/>
<xsl:template match="section | field">
<xsl:element name="{name}">
<xsl:apply-templates select="* except name"/>
</xsl:element>
</xsl:template>
<xsl:template match="*[name]/value">
<asCurrent>
<xsl:apply-templates/>
</asCurrent>
</xsl:template>
<xsl:template match="table">
<xsl:element name="{name}">
<xsl:apply-templates select="* except name"/>
<maxPK>
<xsl:value-of select="count(tableRow)"/>
</maxPK>
</xsl:element>
</xsl:template>
<xsl:template match="tableRow">
<xsl:element name="{field/name}">
<xsl:apply-templates select="* except name"/>
</xsl:element>
</xsl:template>
<xsl:template match="tableRow/sequence">
<pk>
<xsl:apply-templates/>
</pk>
</xsl:template>
<xsl:template match="tableRow/field[name = 'secondaryPhone']">
<phone>
<xsl:apply-templates select="value"/>
</phone>
</xsl:template>
</xsl:transform>
如果索引正常,请仔细检查是否所有数据都是必需的。如果您需要的只是一个ID,请随意使用联接并仅选择ID。
Timesheet::WorkPeriod.includes(:ship).limit(2000).pluck(:id)
# Depending which ID you need
Timesheet::WorkPeriod.includes(:ship).limit(2000).pluck('ships.id')