如何使用多个内连接加速 sql 查询?
How to speed up sql query with multiple inner joins?
我下面的查询有效,但 return 需要很长时间才能得到结果,我不确定如何优化它以显着减少时间。如果有人有任何建议,请告诉我。
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
我真的不明白你的自定义查询有什么意义。假设你有 employer
的角色(或任何你命名的角色),更好的方法是做类似
的事情
get_users( array( 'role' => 'employer' ) );
return 所有具有 employer
角色的用户。然后你可以使用 php 进一步过滤它,这将快 1000 倍。
更不用说 wp_capabilities
不是一成不变的事实,将 wp_
部分替换为 $wpdb->prefix
实际上会更安全。
在知道用户 ID 后查询元数据总是比直接通过元数据查询更快。
查看查询后发现问题并没有我评论时想的那么简单,我不会删除它,但它是错误的。
我不能保证我构建的查询会更好,尝试一下并将它的 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 相关的所有字段并将它们放入同一个对象中。
我下面的查询有效,但 return 需要很长时间才能得到结果,我不确定如何优化它以显着减少时间。如果有人有任何建议,请告诉我。
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
我真的不明白你的自定义查询有什么意义。假设你有 employer
的角色(或任何你命名的角色),更好的方法是做类似
get_users( array( 'role' => 'employer' ) );
return 所有具有 employer
角色的用户。然后你可以使用 php 进一步过滤它,这将快 1000 倍。
更不用说 wp_capabilities
不是一成不变的事实,将 wp_
部分替换为 $wpdb->prefix
实际上会更安全。
在知道用户 ID 后查询元数据总是比直接通过元数据查询更快。
查看查询后发现问题并没有我评论时想的那么简单,我不会删除它,但它是错误的。
我不能保证我构建的查询会更好,尝试一下并将它的 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 相关的所有字段并将它们放入同一个对象中。