【问题标题】:MySQL temporary table vs where in clauseMySQL 临时表 vs where in 子句
【发布时间】:2018-04-12 09:39:26
【问题描述】:

问题是这样的。

我需要从表User 中获取*,其中phoneNumber 列在phoneNumberArray 中。大约有 300 到 1000 个电话号码。表User 在phoneNumber 上有一个索引,可能包含数百万行。

创建一个临时表UserphoneNumbers 并插入所有电话号码并执行JOIN 或使用简单的WHERE IN 并传递一个包含1000 个电话号码的数组会更好吗?

【问题讨论】:

  • 尝试它们并查看执行计划和统计信息,我猜使用临时表会更昂贵,因为它的构建和填充表
  • 您能否向我们展示一个查询、一些数据或两者兼而有之?
  • 如果您的查询频率较低且电话号码列表是静态的,则最好为电话号码创建临时表。但是如果电话号码列表是动态的,最好使用WHERE IN来减少建表和丢表的次数
  • 我基本上会创建表只查询一次然后删除它。只有在创建新帐户时我才会这样做。我会尝试两者并测试结果
  • WHERE IN ( ... ) 意味着您需要通过许多数字中的任何一个来查找“用户”。这似乎是一个不太可能的用例。

标签: mysql sql mariadb


【解决方案1】:

这是一个有趣的问题。使用第二种方法有很多争论——将值放入数组中。

使用临时表并不是一个不合理的选择,但它会显着增加应用程序的复杂性。它增加了数据库的读写开销。应用程序必须创建表并加载它(数据库将负责删除它)。

如果您确实认为需要此选项,请确保电话号码是表中的主键。这对于性能来说是最佳的。

使用IN——尤其是在 MySQL 中——是一个合理的选择。 MySQL 订购常量IN 列表并使用二进制搜索来查找匹配值。这对于全表扫描最有利。对于这么大的列表,全表扫描可能是最有效的方法。

就个人而言,我将从IN 列表开始。使用包含 1,000 个元素的 IN 列表生成查询与包含 3 个元素的列表的代码复杂度相同。如果这不能满足您的需求,请使用临时表尝试性能。如果效果更好,那么就采用这种方法。

【讨论】:

    【解决方案2】:

    我认为第一种方法更清晰,更便于维护。

    如果有一天您想从临时表切换到持久表,那会更容易。

    关于性能,已经有topic about it:

    我怀疑如果您在 WHERE 子句中执行此操作,则计划者正在选择 更有效的路线(即基于索引或预先 过滤数据集)。

    您可以通过 在两列上添加索引(不确定是否包含列和 Postgres 还支持多列索引)。

    【讨论】:

    • 感谢您的回答。关于这个主题有几个帖子,但你总是最终决定引擎是否会进行优化。由于许多答案已经存在多年,因此很难知道引擎在 2017 年会做什么。
    • 你说得对,但我处理的数据量非常大(数十亿),两种方法在性能方面的差异并不显着。所以,我认为正确的方法是您在易读性方面更喜欢的方法。
    猜你喜欢
    • 1970-01-01
    • 2011-08-24
    • 1970-01-01
    • 1970-01-01
    • 2010-12-07
    • 2012-07-19
    • 1970-01-01
    • 2019-01-15
    • 1970-01-01
    相关资源
    最近更新 更多