我为工作编写了一个自定义帮助台,它一直运行良好……直到最近。一个查询确实变慢了。现在大约需要 14 秒!以下是相关表格:
CREATE TABLE `tickets` (
`id` int(11) unsigned NOT NULL DEFAULT '0',
`date_submitted` datetime DEFAULT NULL,
`date_closed` datetime DEFAULT NULL,
`first_name` varchar(50) DEFAULT NULL,
`last_name` varchar(50) DEFAULT NULL,
`email` varchar(50) DEFAULT NULL,
`description` text,
`agent_id` smallint(5) unsigned NOT NULL DEFAULT '1',
`status` smallint(5) unsigned NOT NULL DEFAULT '1',
`priority` tinyint(4) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `date_closed` (`date_closed`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `solutions` (
`id` int(10) unsigned NOT NULL,
`ticket_id` mediumint(8) unsigned DEFAULT NULL,
`date` datetime DEFAULT NULL,
`hours_spent` float DEFAULT NULL,
`agent_id` smallint(5) unsigned DEFAULT NULL,
`body` text,
PRIMARY KEY (`id`),
KEY `ticket_id` (`ticket_id`),
KEY `date` (`date`),
KEY `hours_spent` (`hours_spent`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
当用户提交工单时,它会进入“工单”表。然后,当代理人解决问题时,他们记录下他们采取的行动。每个条目都进入“解决方案”表。换句话说,门票有很多解决方案。
已减慢查询的目标是从“票”表中提取所有字段,并从“解决方案”表中提取最新条目。这是我一直在使用的查询:
SELECT tickets.*,
(SELECT CONCAT_WS(" * ", DATE_FORMAT(solutions.date, "%c/%e/%y"), solutions.hours_spent, CONCAT_WS(": ", solutions.agent_id, solutions.body))
FROM solutions
WHERE solutions.ticket_id = tickets.id
ORDER BY solutions.date DESC, solutions.id DESC
LIMIT 1
) AS latest_solution_entry
FROM tickets
WHERE tickets.date_closed IS NULL
OR tickets.date_closed >= '2012-06-20 00:00:00'
ORDER BY tickets.id DESC
这是“latest_solution_entry”字段的示例:
6/20/12 * 1337 * 1: I restarted the computer and that fixed the problem. Yes, I took an hour to do this.
在 PHP 中,我拆分了“latest_solution_entry”字段并正确设置了格式。
当我注意到运行查询的页面速度变慢时,方式 变慢了,我在没有子查询的情况下运行了查询,而且速度非常快。然后我在原始查询上运行了一个 EXPLAIN 并得到了这个:
+----+--------------------+-----------+-------+---------------+-----------+---------+---------------------+-------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-----------+-------+---------------+-----------+---------+---------------------+-------+-----------------------------+
| 1 | PRIMARY | tickets | index | date_closed | PRIMARY | 4 | NULL | 35804 | Using where |
| 2 | DEPENDENT SUBQUERY | solutions | ref | ticket_id | ticket_id | 4 | helpdesk.tickets.id | 1 | Using where; Using filesort |
+----+--------------------+-----------+-------+---------------+-----------+---------+---------------------+-------+-----------------------------+
所以我正在寻找一种方法来提高我的查询效率,但仍能达到相同的目标。有什么想法吗?
最佳答案
让我总结一下我的理解:您想选择每张票及其最后的解决方案。
我喜欢对这类问题使用以下模式,因为它避免了子查询模式,因此在需要性能的地方相当不错。缺点是理解起来有点棘手:
SELECT
t.*,
s1.*
FROM tickets t
INNER JOIN solutions s1 ON t.id = s1.ticket_id
LEFT JOIN solutions s2 ON s1.ticket_id = s2.ticket_id AND s2.id > s1.id
WHERE s2.id IS NULL;
为了更好地理解,我只写了模式的核心部分。
关键是:
solutions 的左连接表本身与 s1.ticket_id = s2.ticket_id条件:它模拟 GROUP BY ticket_id .
条件 s2.id > s1.id :它是“我只想要最后一个解决方案”的 SQL,它模拟 MAX() .我假设在你的模型中,the last表示 with the greatest id但你可以在这里使用日期条件。注意 s2.id < s1.id会给你第一个解决方案。
WHERE 子句 s2.id IS NULL :最奇怪但绝对必要的...只保留您想要的记录。
试一试,让我知道:)
编辑 1: 我刚刚意识到第二点假设过于简单化了问题。这让它变得更加有趣 :p 我正在尝试查看此模式如何与您的 date, id 一起使用订购。
编辑 2: 好吧,稍作改动后效果很好。 LEFT JOIN 的条件变为:
LEFT JOIN solutions s2 ON s1.ticket_id = s2.ticket_id
AND (s2.date > s1.date OR (s2.date = s1.date AND s2.id > s1.id))
关于MySQL:我可以进行左连接并只从连接表中拉出一行吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11131237/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
查看Ruby的CSV库的文档,我非常确定这是可能且简单的。我只需要使用Ruby删除CSV文件的前三列,但我没有成功运行它。 最佳答案 csv_table=CSV.read(file_path_in,:headers=>true)csv_table.delete("header_name")csv_table.to_csv#=>ThenewCSVinstringformat检查CSV::Table文档:http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV/Table.html
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以
我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的
这是一道面试题,我没有答对,但还是很好奇怎么解。你有N个人的大家庭,分别是1,2,3,...,N岁。你想给你的大家庭拍张照片。所有的家庭成员都排成一排。“我是家里的friend,建议家庭成员安排如下:”1岁的家庭成员坐在这一排的最左边。每两个坐在一起的家庭成员的年龄相差不得超过2岁。输入:整数N,1≤N≤55。输出:摄影师可以拍摄的照片数量。示例->输入:4,输出:4符合条件的数组:[1,2,3,4][1,2,4,3][1,3,2,4][1,3,4,2]另一个例子:输入:5输出:6符合条件的数组:[1,2,3,4,5][1,2,3,5,4][1,2,4,3,5][1,2,4,5,3][
我使用的是Firefox版本36.0.1和Selenium-Webdrivergem版本2.45.0。我能够创建Firefox实例,但无法使用脚本继续进行进一步的操作无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055)错误。有人能帮帮我吗? 最佳答案 我遇到了同样的问题。降级到firefoxv33后一切正常。您可以找到旧版本here 关于ruby-无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055),我们在StackOverflow上找到一个类