我有一些查询花了太长时间(300毫秒),因为数据库已经增长到几百万条记录。幸运的是,对我来说,查询不需要查看大部分数据,最新的100,000条记录就足够了,所以我的计划是维护一个包含最新100,000条记录的单独表格并针对此运行查询。如果有人对更好的方法有任何建议,这将是伟大的。我真正的问题是,如果查询确实需要针对历史数据运行,有哪些选项,下一步是什么?我想到的事情:
这些事情是否正确,还有其他选择吗?有些数据库提供商比其他数据库提供商有更多功能来处理这些问题,例如指定一个特定的表/索引完全在内存中?
抱歉,我应该提到这个,我正在使用mysql。
我忘记在上面提到索引了。到目前为止,索引是我唯一的改进来源。为了识别瓶颈,我一直在使用maatkit进行查询,以显示是否正在使用索引。
我知道我现在正在远离问题的目的,所以也许我应该再做一个问题。我的问题是EXPLAIN
表示查询需要10毫秒而不是jmsofiler报告的300毫秒。如果有人有任何建议我会非常感激。查询是:
select bv.*
from BerthVisit bv
inner join BerthVisitChainLinks on bv.berthVisitID = BerthVisitChainLinks.berthVisitID
inner join BerthVisitChain on BerthVisitChainLinks.berthVisitChainID = BerthVisitChain.berthVisitChainID
inner join BerthJourneyChains on BerthVisitChain.berthVisitChainID = BerthJourneyChains.berthVisitChainID
inner join BerthJourney on BerthJourneyChains.berthJourneyID = BerthJourney.berthJourneyID
inner join TDObjectBerthJourneyMap on BerthJourney.berthJourneyID = TDObjectBerthJourneyMap.berthJourneyID
inner join TDObject on TDObjectBerthJourneyMap.tdObjectID = TDObject.tdObjectID
where
BerthJourney.journeyType='A' and
bv.berthID=251860 and
TDObject.headcode='2L32' and
bv.depTime is null and
bv.arrTime > '2011-07-28 16:00:00'
,EXPLAIN
的输出为:
+----+-------------+-------------------------+-------------+---------------------------------------------+-------------------------+---------+------------------------------------------------+------+-------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------------------+-------------+---------------------------------------------+-------------------------+---------+------------------------------------------------+------+-------------------------------------------------------+
| 1 | SIMPLE | bv | index_merge | PRIMARY,idx_berthID,idx_arrTime,idx_depTime | idx_berthID,idx_depTime | 9,9 | NULL | 117 | Using intersect(idx_berthID,idx_depTime); Using where |
| 1 | SIMPLE | BerthVisitChainLinks | ref | idx_berthVisitChainID,idx_berthVisitID | idx_berthVisitID | 8 | Network.bv.berthVisitID | 1 | Using where |
| 1 | SIMPLE | BerthVisitChain | eq_ref | PRIMARY | PRIMARY | 8 | Network.BerthVisitChainLinks.berthVisitChainID | 1 | Using where; Using index |
| 1 | SIMPLE | BerthJourneyChains | ref | idx_berthJourneyID,idx_berthVisitChainID | idx_berthVisitChainID | 8 | Network.BerthVisitChain.berthVisitChainID | 1 | Using where |
| 1 | SIMPLE | BerthJourney | eq_ref | PRIMARY,idx_journeyType | PRIMARY | 8 | Network.BerthJourneyChains.berthJourneyID | 1 | Using where |
| 1 | SIMPLE | TDObjectBerthJourneyMap | ref | idx_tdObjectID,idx_berthJourneyID | idx_berthJourneyID | 8 | Network.BerthJourney.berthJourneyID | 1 | Using where |
| 1 | SIMPLE | TDObject | eq_ref | PRIMARY,idx_headcode | PRIMARY | 8 | Network.TDObjectBerthJourneyMap.tdObjectID | 1 | Using where |
+----+-------------+-------------------------+-------------+---------------------------------------------+-------------------------+---------+------------------------------------------------+------+---------------------------------------
7 rows in set (0.01 sec)
答案 0 :(得分:3)
explain
以查看它是否有效地使用了索引。 答案 1 :(得分:1)
好吧,如果你已经优化了数据库和查询,我会说,而不是砍掉数据,下一步是看看:
a)mysql配置并确保它充分利用了硬件
b)看看硬件。你没有说你正在使用什么硬件。如果您可以购买两台或三台服务器来分配数据库中的读取,则可能会发现复制是一种选择(必须对中央服务器进行写入,但可以从任意数量的从站读取读取)答案 2 :(得分:1)
考虑到这样的设计更改并不是一个好兆头 - 我敢打赌你仍然有足够的性能来挤出使用EXPLAIN,调整db变量并改进索引和查询。但是你可能已经超越了“尝试的东西”非常有效的地步。这是一个学习如何解释分析和日志的机会,并将您学到的知识用于索引和查询的具体改进。
如果您的建议很好,您应该能够告诉我们原因。请注意,这是一种流行的悲观情绪 -
答案 3 :(得分:1)
不要为最新结果创建单独的表,而是考虑表分区。 MySQL自5.1版以来内置了此功能
只是说清楚:我不是说这是你问题的解决方案。只有一件事你可以尝试
答案 4 :(得分:0)
我首先尝试在采用您列出的任何措施之前优化表/索引/查询。你是否已经深入研究了性能不佳的查询,以至于你绝对相信你已经达到了RDBMS能力的极限?
编辑:如果您确实已经正确优化但仍有问题,请考虑为您需要的确切数据创建物化视图。基于比你提供的更多因素,这可能是也可能不是一个好主意,但我会把它放在需要考虑的事项列表的顶部。
答案 5 :(得分:0)
在最后100,000条记录中搜索应该非常快,你肯定会遇到索引问题。使用EXPLAIN并修复它。
答案 6 :(得分:0)
我知道我现在正在远离问题的目的 所以也许我应该再做一个。我的问题是EXPLAIN说的 jprofiler报告的查询需要10毫秒而不是300毫秒。 的
然后你的问题(和解决方案)必须在java中,对吗?