【问题标题】:How to speed up sql query with multiple inner joins?如何使用多个内连接加速 sql 查询?
【发布时间】:2018-09-05 16:14:37
【问题描述】:

我的下面的查询有效,但返回结果需要很长时间,我不确定如何优化它以显着减少时间。如果有人有任何建议,请给我建议。

SELECT DISTINCT 
                u.ID,
                u.user_email,
                u.display_name,
                m.user_id,
                m1.meta_value AS first_name,
                m2.meta_value AS last_name,
                m3.meta_value AS descriptions,
                m4.meta_value AS company_name,
                m5.meta_value AS company_website,
                m6.meta_value AS phone,
                m7.meta_value AS company_address,
                m8.meta_value AS scategory,
                m9.meta_value AS facebook,
                m10.meta_value AS twitter,
                m11.meta_value AS linkedin,
                m12.meta_value AS youtube,
                m13.meta_value AS instagram,
                m14.meta_value AS googleplus,
                m15.meta_value AS specialties,
                m16.meta_value AS company_logo
           FROM $wpdb->users u 
           INNER JOIN $wpdb->usermeta m ON (m.user_id = u.ID)
           INNER JOIN $wpdb->usermeta m1 ON (m1.user_id = u.ID AND m1.meta_key = 'first_name')
           INNER JOIN $wpdb->usermeta m2 ON (m2.user_id = u.ID AND m2.meta_key = 'last_name')
           INNER JOIN $wpdb->usermeta m3 ON (m3.user_id = u.ID AND m3.meta_key = 'description')
           INNER JOIN $wpdb->usermeta m4 ON (m4.user_id = u.ID AND m4.meta_key = 'company_name')
           INNER JOIN $wpdb->usermeta m5 ON (m5.user_id = u.ID AND m5.meta_key = 'company_website')
           INNER JOIN $wpdb->usermeta m6 ON (m6.user_id = u.ID AND m6.meta_key = 'phone')
           INNER JOIN $wpdb->usermeta m7 ON (m7.user_id = u.ID AND m7.meta_key = 'company_address')
           INNER JOIN $wpdb->usermeta m8 ON (m8.user_id = u.ID AND m8.meta_key = 'scategory')
           INNER JOIN $wpdb->usermeta m9 ON (m9.user_id = u.ID AND m9.meta_key = 'facebook')
           INNER JOIN $wpdb->usermeta m10 ON (m10.user_id = u.ID AND m10.meta_key = 'twitter')
           INNER JOIN $wpdb->usermeta m11 ON (m11.user_id = u.ID AND m11.meta_key = 'linkedin')
           INNER JOIN $wpdb->usermeta m12 ON (m12.user_id = u.ID AND m12.meta_key = 'youtube')
           INNER JOIN $wpdb->usermeta m13 ON (m13.user_id = u.ID AND m13.meta_key = 'instagram')
           INNER JOIN $wpdb->usermeta m14 ON (m14.user_id = u.ID AND m14.meta_key = 'googleplus')
           INNER JOIN $wpdb->usermeta m15 ON (m15.user_id = u.ID AND m15.meta_key = 'specialties')
           INNER JOIN $wpdb->usermeta m16 ON (m16.user_id = u.ID AND m16.meta_key = 'company_logo')
           WHERE m.meta_key = 'wp_capabilities' 
           AND m.meta_value LIKE '%employer%' 
           ORDER BY u.ID

【问题讨论】:

  • 为什么不只使用 1 个连接?全部在m
  • 请告诉我们EXPLAIN 输出。
  • 我看到你可以只使用一个连接和一个 where 语句。
  • @LucasWieloch 你能帮我构建一个单一的连接吗?
  • 感谢所有提供帮助的人,但我采用了@dingo_d 推荐的更简单的方法

标签: php sql wordpress pivot-table entity-attribute-value


【解决方案1】:

我真的不明白您的自定义查询的意义。假设您拥有employer(或您命名的任何名称)的角色,更好的方法是执行类似

get_users( array( 'role' => 'employer' ) );

这应该返回所有具有employer 角色的用户。然后你可以用php进一步过滤,会快1000倍。

更不用说wp_capabilities 并非一成不变,实际上将wp_ 部分替换为$wpdb->prefix 会更安全。

一旦知道用户 ID 后查询元数据总是比直接查询元数据更快。

【讨论】:

    【解决方案2】:

    查看查询后发现问题并不像我评论时想象的那么简单,我不会删除它,但它是错误的。

    我不能保证我建立的查询会更好,试试看,比较一下EXPLAIN和当前的:

    SELECT DISTINCT 
          u.ID,
          u.user_email,
          u.display_name,
          m.user_id,
          SELECT t.meta_value FROM m WHERE m.meta_key = 'first_name' AS first_name,
          SELECT t.meta_value FROM m WHERE m.meta_key = 'last_name' AS last_name,
          SELECT t.meta_value FROM m WHERE m.meta_key = 'descriptions' AS descriptions,
          SELECT t.meta_value FROM m WHERE m.meta_key = 'company_name' AS company_name,
          SELECT t.meta_value FROM m WHERE m.meta_key = 'company_website' AS company_website,
          SELECT t.meta_value FROM m WHERE m.meta_key = 'phone' AS phone,
          SELECT t.meta_value FROM m WHERE m.meta_key = 'company_address' AS company_address,
          SELECT t.meta_value FROM m WHERE m.meta_key = 'scategory' AS scategory,
          SELECT t.meta_value FROM m WHERE m.meta_key = 'facebook' AS facebook,
          SELECT t.meta_value FROM m WHERE m.meta_key = 'twitter' AS twitter,
          SELECT t.meta_value FROM m WHERE m.meta_key = 'linkedin' AS linkedin,
          SELECT t.meta_value FROM m WHERE m.meta_key = 'youtube' AS youtube,
          SELECT t.meta_value FROM m WHERE m.meta_key = 'instagram' AS instagram,
          SELECT t.meta_value FROM m WHERE m.meta_key = 'googleplus' AS googleplus,
          SELECT t.meta_value FROM m WHERE m.meta_key = 'specialties' AS specialties,
          SELECT t.meta_value FROM m WHERE m.meta_key = 'company_logo' AS company_logo
     FROM $wpdb->users u 
     INNER JOIN $wpdb->usermeta m ON (m.user_id = u.ID)
     WHERE m.meta_key = 'wp_capabilities' 
     AND m.meta_value LIKE '%employer%' 
     ORDER BY u.ID
    

    这是使用子查询而不是多个JOIN 语句的相同查询。我建议您改为执行以下查询:

    WITH cte(u_id, email, display_name, m_user_id)
     AS
     (
       SELECT 
           u.ID,
           u.user_email,
           u.display_name,
           m.user_id
       FROM $wpdb->users u 
       INNER JOIN $wpdb->usermeta m ON (m.user_id = u.ID)
       WHERE m.meta_key = 'wp_capabilities' 
       AND m.meta_value LIKE '%employer%' 
     )
     SELECT 
        u.u_id,
        u.email,
        u.display_name,
        u.m_user_id,
        m.meta_key,
        m.meta_value
    FROM cte u
    INNER JOIN $wpdb->usermeta m ON (m.user_id = u.u_id)
    WHERE m.meta_key IN ('first_name'
                          'last_name'
                          'descriptions'
                          'company_name'
                          'company_website'
                          'phone'
                          'company_address'
                          'scategory'
                          'facebook'
                          'twitter'
                          'linkedin'
                          'youtube'
                          'instagram'
                          'googleplus'
                          'specialties'
                          'company_logo')
    ORDER BY u.u_id
    

    第二个查询将带来您需要的所有数据,您只需在代码中执行一些操作以获取与用户 ID 相关的所有字段并将它们放在同一个对象中。

    【讨论】:

      猜你喜欢
      • 2018-04-21
      • 2020-08-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-17
      • 2012-04-27
      • 2020-09-13
      相关资源
      最近更新 更多