查询成百万条记录时速度较慢MariaDB

问题描述 投票:0回答:2

我安装了一个插件,并在后端进行了优化(SSD,对GROUP BY&WHERE中调用的列进行单列索引)但是在运行此查询时

SELECT  u.user_id, u.profile_page_id, u.server_id AS user_server_id, u.user_name, u.full_name, u.gender, u.user_image, u.is_invisible, u.user_group_id, u.language_id, u.birthday, u.country_iso, m.*
FROM(
(SELECT m.*
FROM phpfox_channel_video AS m
INNER JOIN phpfox_channel_category AS mc
    ON(mc.category_id = mc.category_id)
INNER JOIN phpfox_channel_category_data AS mcd
    ON(mcd.video_id = m.video_id)

WHERE m.in_process = 0 AND m.view_id = 0 AND m.module_id = 'videochannel' AND m.item_id = 0 AND m.privacy IN(0) AND mcd.category_id = 17
GROUP BY m.video_id
ORDER BY m.time_stamp DESC
)) AS m
JOIN phpfox_user AS u
    ON(u.user_id = m.user_id)

ORDER BY m.time_stamp DESC
LIMIT 24;

需要20秒,而改为更改为此时间

SELECT  u.user_id, u.profile_page_id, u.server_id AS user_server_id, u.user_name, u.full_name, u.gender, u.user_image, u.is_invisible, u.user_group_id, u.language_id, u.birthday, u.country_iso, m.*
FROM(
(SELECT  m.*
FROM phpfox_channel_video AS m
INNER JOIN phpfox_channel_category_data AS mcd
    ON(mcd.video_id = m.video_id AND mcd.category_id = 17)
WHERE m.in_process = 0 AND m.view_id = 0 AND m.module_id = 'videochannel' AND m.item_id = 0 AND m.privacy IN(0) 
GROUP BY m.video_id
ORDER BY m.time_stamp DESC
)) AS m
JOIN phpfox_user AS u
    ON(u.user_id = m.user_id)

ORDER BY m.time_stamp DESC
LIMIT 24;

此过程大约需要5-6秒

phpfox_channel_video包含200万行(并将继续快速添加,它是一个社交媒体网站,用户也可以上传文件),因此缓存不是很有用(但已激活)。

关于如何优化它的任何提示?我对MariaDB / MySQL的经验最少,因为我已经习惯于使用MS SQL处理大数据并创建自己的结构。无需对表做太多改动的任何推荐方法(添加表即可)。

或者我应该重组PHP&表以将查询优化为低于1秒/查询。谢谢!

我找到了这些链接http://mysql.rjweb.org/doc.php/memoryhttp://mysql.rjweb.org/doc.php/ricksrots#indexing

它们仍然有用吗?

附上解释结果enter image description here对于索引,当前配置被设置为索引,每一列都被声明为索引键,上面查询中涉及的所有所有表。

打印当前的服务器配置是否有帮助?谢谢!

mysql mariadb
2个回答
0
投票

我在检查表后设法清理查询,结果证明是这样

WHERE m.in_process = 0 AND m.view_id = 0 AND m.module_id = 'videochannel' AND m.item_id = 0 AND m.privacy IN(0) 

不需要运行,因为所有表都符合该条件..(对于本网站的当前情况)。所以我只是优化那些长查询。并且设法击中<1秒..


0
投票
INNER JOIN  phpfox_channel_category AS mc ON(mc.category_id = mc.category_id)

是否几乎没有用。

  • 您不将mc的任何列用于其他目的。
  • 执行此JOIN
  • JOIN验证了mc中存在相应的行。
  • 如果存在multiple个对应的行,则此JOIN将膨胀临时表。
  • 膨胀导致GROUP BY中的工作浪费。

类似地,您的第二个查询不使用mcd

请对派生表使用不同的别名。很难遵循m.的多种用法。

这完全没用:

ORDER BY  m.time_stamp DESC

MySQL / MariaDB可以随意忽略派生表中的ORDER BY。一个表被定义为无序行集合。订购只能在最后完成。

建议索引

m: INDEX(item_id, module_id, view_id, in_process, -- any order; tested with '='
         privacy,   -- sometimes has a list?
         video_id)  -- last
mcd:  INDEX(category_id, video_id)  -- in either order

有一种更合乎逻辑的方法,并且可能更快:

    INNER JOIN  phpfox_channel_category_data AS mcd
          ON  mcd.video_id = m.video_id
         AND  mcd.category_id = 17

删除,然后删除GROUP BY m.id,然后将其添加到WHERE

AND EXISTS( SELECT 1 FROM phpfox_channel_category_data AS mcd
               WHERE  mcd.video_id = m.video_id
                 AND  mcd.category_id = 17 )

(上述索引仍然适用。)

不是我也许已经消除了两个“文件排序”-GROUP BYORDER BY。另一个注意事项:EXPLAIN并不总是显示实际有多少个文件排序。 (但是EXPLAIN FORMAT=JSON SELECT ...是。)

© www.soinside.com 2019 - 2024. All rights reserved.