Mysql 如何提高此joomla查询的性能?
我正在尝试将一些joomla用户数据传递给Datatable(jQuery插件)。 涉及到4个表Mysql 如何提高此joomla查询的性能?,mysql,joomla2.5,database-performance,Mysql,Joomla2.5,Database Performance,我正在尝试将一些joomla用户数据传递给Datatable(jQuery插件)。 涉及到4个表 joo_用户(~10k行) joo_用户组(~1.7k行) joo\u user\u usergroup\u map(~56k行) joo\u用户配置文件(~1398k行) 现在查询: SELECT SQL_CALC_FOUND_ROWS a.id, a.name, MAX( IF(profiles.profile_key = 'profile.email', profi
(~10k行)joo_用户
(~1.7k行)joo_用户组
(~56k行)joo\u user\u usergroup\u map
(~1398k行)joo\u用户配置文件
SELECT SQL_CALC_FOUND_ROWS
a.id,
a.name,
MAX( IF(profiles.profile_key = 'profile.email', profiles.profile_value, NULL) ) AS email,
MAX( IF(profiles.profile_key = 'profile.codice_agente', profiles.profile_value, NULL) ) AS codice_agente,
MAX( IF(profiles.profile_key = 'profile.codice_agente_fisso', profiles.profile_value, NULL) ) AS codice_agente_fisso,
MAX( IF(profiles.profile_key = 'profile.codice_agente_VAR', profiles.profile_value, NULL) ) AS codice_agente_VAR,
MAX( IF(profiles.profile_key = 'profile.cellulare', profiles.profile_value, NULL) ) AS cellulare,
(SELECT
GROUP_CONCAT(DISTINCT b.title)
FROM
joo_user_profiles AS up
LEFT JOIN
joo_usergroups AS b ON REPLACE(up.profile_value, '"', '') = b.id
WHERE
up.profile_key LIKE 'profile.agenzia_%'
AND up.user_id = a.id
AND profile_value != '""') AS agenzia,
GROUP_CONCAT(DISTINCT REPLACE(IF(profiles.profile_key LIKE 'profile.canale_%' AND profiles.profile_value = '1', profiles.profile_key, NULL),'profile.canale_','') ) AS canale,
GROUP_CONCAT(DISTINCT IF(profiles.profile_key LIKE 'profile.area_%' AND profiles.profile_value != '""', profiles.profile_value, NULL)) AS area,
(SELECT
GROUP_CONCAT(DISTINCT b.title)
FROM
joo_user_profiles AS up
LEFT JOIN
joo_usergroups AS b ON REPLACE(up.profile_value, '"', '') = b.id
WHERE
up.profile_key LIKE 'profile.ruolo_%'
AND up.user_id = a.id
AND profile_value != '"0"') AS ruolo,
GROUP_CONCAT(IF(profiles.profile_key LIKE 'profile.status_%' AND profiles.profile_value != '""', profiles.profile_value, NULL)) AS status
FROM `joo_users` as a
LEFT JOIN joo_user_profiles AS profiles ON a.id = profiles.user_id
GROUP BY id
ORDER BY id
asc
LIMIT 0, 20
这个beast在生产服务器上需要40秒,这是不可接受的
我知道视图不会带来任何性能提升,我已经为我能想到的每一列建立了索引。
你有什么建议吗?我不知道你为什么需要计算行,但把它放在那里了。 至于查询,由于您的所有组_concat都主要针对概要文件表和可选的用户组,因此我做了一个预查询(通过tmpGrpCat别名),仅使用相应的组_concat和max()对电子邮件、条件…、单元格、,等。我还将其包括在预查询中,以排除配置文件值不是“”的情况,因为对于您感兴趣的值来说,这似乎是一致的 然后,我在users表上做了一个简单的左连接,以获取他们的id/name和其他聚合。这应该可以简化引擎,让它对每个profile_key LIKE(或equality)条件的所有记录运行一次,按用户ID对它们进行分组,然后准备进行最外层的查询 如果这有效,请让我们了解性能改进。If将来也可以在性能技术方面帮助他人
SELECT SQL_CALC_FOUND_ROWS
a.id,
a.name,
coalesce( tmpGrpCat.email, '' ) as email,
coalesce( tmpGrpCat.codice_agente, '' ) as codice_agente,
coalesce( tmpGrpCat.codice_agente_fisso, '' ) as codice_agente_fisso,
coalesce( tmpGrpCat.codice_agente_VAR, '' ) as codice_agente_VAR,
coalesce( tmpGrpCat.cellulare, '' ) as cellulare,
coalesce( tmpGrpCat.AgTitle, '' ) as Agenzia,
coalesce( tmpGrpCat.RuoloTitle, '' ) as ruolo,
coalesce( tmpGrpCat.Canale, '' ) as Canale,
coalesce( tmpGrpCat.Area, '' ) as Area,
coalesce( tmpGrpCat.Status, '' ) as Status
FROM
joo_users as a
LEFT JOIN
( SELECT
up.user_id,
GROUP_CONCAT( DISTINCT IF( up.profile_key LIKE 'profile.agenzia_%', b.title, NULL )) AgTitle,
GROUP_CONCAT( DISTINCT IF( up.profile_key LIKE 'profile.ruolo_%', b.title, NULL )) RuoloTitle,
GROUP_CONCAT( DISTINCT IF( up.profile_key LIKE 'profile.canale_%' AND up.profile_value = '1',
REPLACE( up.profile_key, 'profile.canale_',''), NULL)) AS canale,
GROUP_CONCAT( DISTINCT IF( up.profile_key LIKE 'profile.area_%',
up.profile_value, NULL)) AS area,
GROUP_CONCAT( DISTINCT IF( up.profile_key LIKE 'profile.status_%',
up.profile_value, NULL)) AS status,
MAX( IF( up.profile_key = 'profile.email', up.profile_value, NULL) ) AS email,
MAX( IF( up.profile_key = 'profile.codice_agente', up.profile_value, NULL) ) AS codice_agente,
MAX( IF( up.profile_key = 'profile.codice_agente_fisso', up.profile_value, NULL) ) AS codice_agente_fisso,
MAX( IF( up.profile_key = 'profile.codice_agente_VAR', up.profile_value, NULL) ) AS codice_agente_VAR,
MAX( IF( up.profile_key = 'profile.cellulare', up.profile_value, NULL) ) AS cellulare
FROM
joo_user_profiles AS up
LEFT JOIN joo_usergroups AS b
ON REPLACE(up.profile_value, '"', '') = b.id
WHERE
( up.profile_key LIKE 'profile.agenzia_%'
OR up.profile_key LIKE 'profile.ruolo_%'
OR up.profile_key LIKE 'profile.canale_%'
OR up.profile_key LIKE 'profile.area_%'
OR up.profile_key LIKE 'profile.status_%'
OR up.profile_key = 'profile.email'
OR up.profile_key = 'profile.codice_agente'
OR up.profile_key = 'profile.codice_agente_fisso'
OR up.profile_key = 'profile.codice_agente_VAR'
OR up.profile_key = 'profile.cellulare' )
AND up.profile_value != '""'
AND up.profile_value != '"0"'
GROUP BY
up.user_id ) as tmpGrpCat
ON a.id = tmpGrpCat.user_id
ORDER BY
id asc
LIMIT
0, 20
由于您是在Joomla中执行此查询,因此可以尝试使用Tabulizer for Joomla(),它可以通过使用数据源缓存(用于查询结果)和ajax加载来处理大数据集,因此最初只提取表的第一页,只有在需要时才提取其余数据。当然,查询需要至少执行一次才能填充缓存,因此您必须进一步改进它或增加可用的系统资源(PHP内存和最大执行时间)。这很可能是它在服务器上而不是本地服务器上失败的原因,因为大多数共享托管环境的PHP脚本执行时间最长为30秒。这些连接条件非常糟糕。只要你有这些,你就会被糟糕的性能所困扰。重新设计并尝试将你的逻辑分割成更小的部分。我确实观察到我的本地机器有10倍的改进,但由于某种原因,当我在服务器上运行quey时,它会无限期地挂起(几分钟后我停止了它)我的开发机器是mysql 5.6,而服务器是5.5,但我怀疑这可能是问题所在。