Как ускорить SQL-запрос с несколькими внутренними объединениями? - PullRequest
0 голосов
/ 05 сентября 2018

Мой запрос, приведенный ниже, работает, но для возврата результата требуется вечность, я не уверен, как его можно оптимизировать, чтобы значительно сократить время. Если у кого-то есть предложения, пожалуйста, сообщите мне.

Спасибо заранее.

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

Ответы [ 2 ]

0 голосов
/ 05 сентября 2018

Изучив запрос, я понял, что проблема не так проста, как я думал, когда комментировал, я не буду удалять ее, но это неправильно.

Я не могу гарантировать, что построенный мной запрос будет лучше, попробуйте его и сравните 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

Этот второй запрос принесет все необходимые данные, вам просто нужно что-то сделать в своем коде, чтобы взять все поля, относящиеся к идентификатору пользователя, и поместить их в один и тот же объект.

0 голосов
/ 05 сентября 2018

Я действительно не вижу смысла вашего пользовательского запроса. Предполагая, что у вас есть роль employer (или как вы ее назвали), лучший способ сделать это - сделать что-то вроде

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

Который должен вернуть всех пользователей с ролью employer. Затем вы можете отфильтровать его, используя php, который будет в 1000 раз быстрее.

Не говоря уже о том, что wp_capabilities не установлен в камне, и вы на самом деле безопаснее, если заменить wp_ деталь на $wpdb->prefix.

Также запрос метаданных, когда вы знаете, что идентификатор пользователя всегда будет быстрее, чем запрос непосредственно метаданными.

...