【问题标题】:How can I check if a value appears in a different table more efficiently?如何更有效地检查值是否出现在不同的表中?
【发布时间】:2014-01-12 21:39:58
【问题描述】:

我可以使用我在下面编写的查询来获取必要的结果。可悲的是,这需要我通过一个带有子查询的巨大表,每次执行查询都需要 10 秒以上。有没有更有效的方法来做到这一点?

SELECT * FROM CATEGORIES
WHERE ID IN (SELECT DISTINCT replace( CATEGORY, '-', '' ) 
FROM `LISTINGS`) LIMIT 0 , 30

注意:类别值在表 LISTINGS 中写为“-1-”,其中 1 是类别 ID。

【问题讨论】:

  • 您可以尝试使用 where '-'+ID+'-' in (select distinct category .. 之类的内容来消除替换 - 我的语法可能有误,您可能需要将 ID 转换为 varchar 才能做到这一点。看起来无论如何您都必须扫描该表。
  • 类别经常变化吗?如果没有,只需将类别 ID 保存在 memcache 中并使用 ID 进行查询。甚至将整个类别对象保存在 memcache 中。在典型用法中,在为最终用户提供服务时,不应有理由从数据库中获取类别。

标签: mysql sql performance subquery


【解决方案1】:

你可以先试试这个:

SELECT *
FROM CATEGORIES c
WHERE exists (SELECT 1 
              FROM `LISTINGS` l
              WHERE c.id = replace(l.CATEGORY, '-', '' ) 
             )
LIMIT 0 , 30;

某些版本的 MySQL 以非常低效的方式实现 in,因此这可能会解决问题。

如果没有,请尝试添加索引listings(category) 并执行以下操作:

SELECT *
FROM CATEGORIES c
WHERE exists (SELECT 1 
              FROM `LISTINGS` l
              WHERE concat('-', c.id, '-') = l.CATEGORY
             )
LIMIT 0 , 30;

这会“反转”比较,但允许 MySQL 使用索引进行查找。

【讨论】:

    【解决方案2】:

    我会假设这个巨大的表是 LISTINGS 并且其中的 CATEGORY 字段是一个索引。

    你需要失去 DISTINCT REPLACE。

    DISTINCT REPLACE (index_field,'a','b') // Using index; Using temporary
    

    这首先替换所有值,然后检查不同的值。 鉴于字段 LISTINGS.CATEGORY 没有 '-1' 和 '-1-' 这样的问题值,您可以使用 distinct like

    DISTINCT index_field // Using index for group-by, faster
    

    并连接表 CATEGORIES 中的字段(我想它的记录要少得多):

    SELECT * FROM CATEGORIES WHERE CONCAT('-',ID,'-') IN 
    (SELECT DISTINCT(CATEGORY) FROM `LISTINGS`)
    

    您也可以考虑永远去掉“-”。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-14
      • 1970-01-01
      • 2017-01-23
      • 1970-01-01
      • 2019-12-29
      相关资源
      最近更新 更多