【发布时间】:2016-09-19 23:51:31
【问题描述】:
我正在尝试解决一个性能问题,即我们在大量非顺序 ID 上运行 WHERE IN 子句。根据this 和 MySQL 性能一书,您可以通过使用相关字段创建临时表并加入您关心的表来提高性能。
我在 ActiveRecord::Base 类中有以下 Rails 代码:
def self.where_in(field, ids)
tmp_table = "tmp_table_#{SecureRandom.uuid.gsub('-', '_')}"
begin
# Create temporary table with one column
connection.execute("CREATE TEMPORARY TABLE #{tmp_table} (param INT NOT NULL PRIMARY KEY) ENGINE=Memory")
# Insert ids into the table (doesn't have to be ids)
vals = ids.map{|i| "(#{i})"}.join(", ")
connection.execute("INSERT INTO #{tmp_table} (param) VALUES #{vals};")
# Return the join relation which is the same as WHERE IN (...)
return self.joins("INNER JOIN #{tmp_table} on #{field} = #{tmp_table}.param").all
ensure
# Drop table after we're done...this is the problem
connection.execute("DROP TEMPORARY TABLE IF EXISTS #{tmp_table}")
end
end
但问题是这会创建一个 SQL 语句,这取决于我在确保语句中删除的临时表的存在。如果我删除了 ensure 语句,它可以正常工作,但是临时表仍然存在。
鉴于此,我的问题是:
除了将表名弹出到后台工作人员以便稍后删除之外,我如何“推迟”删除此表?
或
我是否可以安全地不删除表并假设连接池将获得连接,从而最终删除表?
【问题讨论】:
标签: mysql ruby-on-rails ruby activerecord