gpt4 book ai didi

MySQL 大量行的性能问题

转载 作者:行者123 更新时间:2023-11-30 01:37:40 27 4
gpt4 key购买 nike

我正在开发一个基于XenForo引擎的网站,并且在获取所有线程并连接帖子表和论坛表以获取该线程所属的第一个帖子和论坛的一些信息的查询中遇到问题。查询如下:

SELECT thread . *<br/>
FROM xf_thread AS thread<br/>
INNER JOIN xf_node AS node ON (node.node_id = thread.node_id)<br/>
INNER JOIN xf_post AS post ON (post.post_id = thread.first_post_id)<br/>
WHERE thread.node_id IN ('295', '296', '297', '298', '299', '300', '301', '302', '256', '2575', '258', '259', '260', '253', '254', '255', '127', '163', '159', '144', '145', '146', '147', '148', '164', '165', '166', '167', '168', '169', '170', '162', '171', '173', '172', '128', '129', '130', '131', '132', '133', '134', '135', '136', '137', '138', '139', '140', '141', '142', '143', '151', '152', '153', '154', '155', '157', '156', '158', '161', '160', '149', '227', '232', '237', '233', '236', '234', '235', '238', '248', '240', '241', '242', '239', '246', '247', '243', '244', '245', '228', '229', '230', '231', '249', '250', '251', '174', '190', '195', '199', '193', '191', '197', '198', '192', '200', '204', '207', '205', '203', '206', '202', '208', '201', '187', '176', '177', '178', '189', '188', '180', '186', '184', '185', '182', '183', '181', '179', '209', '211', '217', '218', '219', '210', '212', '213', '214', '215', '216', '220', '222', '223', '224', '221', '225', '261', '291', '276', '272', '270', '265', '277', '267', '286', '292', '289', '274', '264', '287', '278', '282', '279', '281', '280', '283', '284', '285', '290', '275', '268', '263', '266', '294', '262', '293', '269', '273', '288', '271')<br/>
ORDER BY thread.last_post_date DESC<br/>
LIMIT 10

解释查询结果为:

id  select_type table   type    possible_keys   key key_len ref rows    Extra1   SIMPLE  node    index   PRIMARY PRIMARY 4   NULL    199 Using where; Using index; Using temporary; Using filesort1   SIMPLE  thread  ref node_id_last_post_date,node_id_sticky_last_post_date    node_id_last_post_date  4   node.node_id    221  1   SIMPLE  post    eq_ref  PRIMARY PRIMARY 4   thread.first_post_id    1   Using index

Query takes 9+ seconds to execute.

Removing joining of xf_node table, runs the query in 0.01 seconds. Explain looks like

id select_type table   type    possible_keys   key key_len ref rows    Extra1   SIMPLE  thread  index   node_id_last_post_date,node_id_sticky_last_post_da...   last_post_date  4   NULL    69970   Using where1   SIMPLE  post    eq_ref  PRIMARY PRIMARY 4   thread.first_post_id    1   Using index

Removing joining of xf_post table runs the query in 0.01 seconds, explain looks like

id select_type table   type    possible_keys   key key_len ref rows    Extra1   SIMPLE  thread  index   node_id_last_post_date,node_id_sticky_last_post_da...   last_post_date  4   NULL    70840   Using where1   SIMPLE  node    eq_ref  PRIMARY PRIMARY 4   thread.node_id  1   Using index

So, the problem exists only when both tables are joined, but joins themselves seem to be completely correct and work perfectly separately.

Number of rows in the tables - xf_thread: 71,855, xf_node: 178, xf_post: 2,977,326

My assumption is that when both tables are joined MySQL starts to use incorrect indexes, and maybe forcing an index will solve the problem?

Your help and suggestions to find a way to resolve this problem are highly appreciated.

EDIT: Here are create table statements for all tables involved

xf_node

CREATE TABLE `xf_node` (  
`node_id` int(10) unsigned NOT NULL auto_increment,
`title` varchar(50) NOT NULL,
`description` text NOT NULL,
`node_name` varchar(50) default NULL COMMENT 'Unique column used as string ID by some node types',
`node_type_id` varbinary(25) NOT NULL,
`parent_node_id` int(10) unsigned NOT NULL default '0',
`display_order` int(10) unsigned NOT NULL default '1',
`display_in_list` tinyint(3) unsigned NOT NULL default '1' COMMENT 'If 0, hidden from node list. Still counts for lft/rgt.',
`lft` int(10) unsigned NOT NULL default '0' COMMENT 'Nested set info ''left'' value',
`rgt` int(10) unsigned NOT NULL default '0' COMMENT 'Nested set info ''right'' value',
`depth` int(10) unsigned NOT NULL default '0' COMMENT 'Depth = 0: no parent',
`style_id` int(10) unsigned NOT NULL default '0' COMMENT 'Style override for specific node',
`effective_style_id` int(10) unsigned NOT NULL default '0' COMMENT 'Style override; pushed down tree',
PRIMARY KEY (`node_id`),
UNIQUE KEY `node_name_unique` (`node_name`,`node_type_id`),
KEY `parent_node_id` (`parent_node_id`),
KEY `display_order` (`display_order`),
KEY `display_in_list` (`display_in_list`,`lft`),
KEY `lft` (`lft`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=304 ;

<强> xf_post

CREATE TABLE `xf_post` (  
`post_id` int(10) unsigned NOT NULL auto_increment,
`thread_id` int(10) unsigned NOT NULL,
`user_id` int(10) unsigned NOT NULL,
`username` varchar(50) NOT NULL,
`post_date` int(10) unsigned NOT NULL,
`message` mediumtext NOT NULL,
`ip_id` int(10) unsigned NOT NULL default '0',
`message_state` enum('visible','moderated','deleted') NOT NULL default 'visible',
`attach_count` smallint(5) unsigned NOT NULL default '0',
`position` int(10) unsigned NOT NULL,
`likes` int(10) unsigned NOT NULL default '0',
`like_users` blob NOT NULL,
`warning_id` int(10) unsigned NOT NULL default '0',
`warning_message` varchar(255) NOT NULL default '',
PRIMARY KEY (`post_id`),
KEY `thread_id_post_date` (`thread_id`,`post_date`),
KEY `thread_id_position` (`thread_id`,`position`),
KEY `user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=3123657 ;

<强> xf_thread

CREATE TABLE `xf_thread` (  
`thread_id` int(10) unsigned NOT NULL auto_increment,
`node_id` int(10) unsigned NOT NULL,
`title` varchar(150) NOT NULL,
`reply_count` int(10) unsigned NOT NULL default '0',
`view_count` int(10) unsigned NOT NULL default '0',
`user_id` int(10) unsigned NOT NULL,
`username` varchar(50) NOT NULL,
`post_date` int(10) unsigned NOT NULL,
`sticky` tinyint(3) unsigned NOT NULL default '0',
`discussion_state` enum('visible','moderated','deleted') NOT NULL default 'visible',
`discussion_open` tinyint(3) unsigned NOT NULL default '1',
`discussion_type` varchar(25) NOT NULL default '',
`first_post_id` int(10) unsigned NOT NULL,
`first_post_likes` int(10) unsigned NOT NULL default '0',
`last_post_date` int(10) unsigned NOT NULL,
`last_post_id` int(10) unsigned NOT NULL,
`last_post_user_id` int(10) unsigned NOT NULL,
`last_post_username` varchar(50) NOT NULL,
`prefix_id` int(10) unsigned NOT NULL default '0',
PRIMARY KEY (`thread_id`),
KEY `node_id_last_post_date` (`node_id`,`last_post_date`),
KEY `node_id_sticky_last_post_date` (`node_id`,`sticky`,`last_post_date`),
KEY `last_post_date` (`last_post_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=76301 ;

谢谢。

最佳答案

有时mysql中的order by子句会使用临时表对结果进行排序。对于大数据,可能需要花费大量时间。避免使用“order by desc”并在 mysql 之外对数据进行排序。

关于MySQL 大量行的性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16632379/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com