【问题标题】:Slow MySQL SELECT query缓慢的 MySQL SELECT 查询
【发布时间】:2012-05-04 06:58:51
【问题描述】:

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

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

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

Select 查询需要 3-6 秒之间的任何时间,这使得导入另外 600,000 条依赖于此查询的记录完全不切实际。

表索引见附图:

如果我根据 contact.id=123456 进行搜索,那么查询时间会缩短到 0.004 秒左右。 contact.id 是表的主键。 external_identifier 是唯一索引。

【问题讨论】:

  • 你绝对需要select *吗?
  • 否 - 我只是通过将其限制为 SELECT id 来测试它,但查询仍然在 1.5 到 2 秒之间。所以它更好,但仍然太慢。
  • 我现在在一个 7.5GB 的 Amazon EC2 大型实例上运行它。总 DB 大小约为 1GB,因此内存充足。
  • 如果你有一个唯一的数字标识符,它可能应该是 PRIMARY KEY .. 似乎你已经添加了 id 列只是 “因为那是我一直做的” .
  • 这个表使用的是什么引擎?你试过REPAIR TABLE吗?

标签: mysql select civicrm


【解决方案1】:

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

这里的问题多于答案。

【讨论】:

    【解决方案2】:

    我知道这是一个老话题,但由于它与 CiviCRM 相关,我想我会提出我的想法。该修复实际上不是最佳实践,因为您更改了其中一个核心打包表以使您的查询运行得更快。虽然这对你来说可能没问题,但我绝对不会向所有人推荐这个。

    您的解决方案可能已经突出了查询的问题,您似乎在告诉查询您期望一个数字,但实际上数据存储为 VARCHAR。所以我认为简单地在值周围加上单引号就可以了?

    选择 * FROM civicrm_contact 联系方式 WHERE contact.external_identifier = '123456'

    如果没有这个,我很确定(与 Oracle 合作多年)会发生隐式数据类型转换,因此查询将无法使用 INDEX。

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

    谢谢

    帕维兹

    【讨论】:

      【解决方案3】:

      我将结构更改为 INT 类型的 external_identifier 而不是 VARCHAR。速度提升到0.006s

      我还不确定这是否会产生更广泛的影响

      【讨论】:

        【解决方案4】:

        您似乎使用了BTREE 索引。如果您不对该列执行任何范围查询(使用<><=>=),您可能需要使用基于哈希的索引。

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

        并查看here 的确切语法。

        【讨论】:

        • 虽然id 列上的PRIMARY KEY 索引也是BTREE,所以这并不能解释性能差异。
        猜你喜欢
        • 2015-07-30
        • 2021-07-06
        • 2016-01-10
        • 2011-08-04
        • 2012-01-15
        • 1970-01-01
        • 1970-01-01
        • 2022-01-17
        • 2011-11-18
        相关资源
        最近更新 更多