2012-04-23 183 views
0

我有一个缓慢的MySQL SELECT查询,我似乎无法排除故障。缓慢的MySQL SELECT查询

这是一个简单的,在大约600,000条记录的表上。

SELECT * 
FROM `civicrm_contact` contact 
WHERE contact.external_identifier =123456 

SELECT查询需要之间的任何地方3-6秒,这使导入另一个60万点的记录依赖于该查询,完全不切实际。

的表索引示于附加的图像:Table Indexes

如果我搜索基于contact.id = 123456则查询时间下降到约0.004s。 contact.id是表格上的主键。 external_identifier是唯一的索引。

+5

你绝对需要'select *'吗? – nico 2012-04-23 16:23:36

+0

不 - 我只是通过将其限制为SELECT id来测试它,但查询仍在1.5到2秒之间。所以它更好,但仍然太慢。 – bpmccain 2012-04-23 16:29:27

+0

我正在7.5GB Amazon EC2大型实例上运行它。总数据库大小约为1GB,因此有大量内存。 – bpmccain 2012-04-23 16:33:17

回答

0

看来你使用BTREE索引。如果您未对此列执行任何范围查询(使用<,>,<=>=),则可能需要使用基于散列的索引。

有关详细信息,请参见Comparison of B-Tree and Hash Indexes

并参见here确切的语法。

+0

虽然'id'列上的'PRIMARY KEY'索引也是'BTREE',所以这并不能解释性能差异。 – eggyal 2012-04-23 16:46:16

+0

@eggyal同意。 – yair 2012-04-23 16:48:20

0

我改变了结构,使INT类型的external_identifier而不是VARCHAR。速度已经提高到0.006s

我还没有确定这是否将有任何更广泛的影响

1

我知道这是一个古老的线程,但由于涉及到CiviCRM我想我会推我的想法。该修复实际上并不是最佳实践,因为您已更改了核心打包表之一,以加快查询的运行速度。虽然这可能对你有好处,但我绝对不会向每个人推荐这个。

虽然您的解决方案可能突出显示了查询的问题,但您似乎在告诉查询,您希望得到一个数字,但事实上数据存储为VARCHAR。所以我认为只要在价值中加上单引号就可以做到这一点。

SELECT * FROM 接触civicrm_contact WHERE = contact.external_identifier“123456”

没有这个我敢肯定(已与Oracle工作了数年),一个隐式数据类型转换会发生因此查询不能使用INDEX。

解释计划应该证明这个理论。

感谢

帕尔韦兹

0

我半信半疑的数据类型转换为这个问题的。我想知道这是否与索引字段的大小限制有关。作为一个btree意味着索引键可能比散列键要大得多。这是必要的吗?将外部ID保存在一个单独的表中并将它们基于数字ID链接起来会更好吗?

更多的问题比这里的答案真的。