简体   繁体   English

使用简单的自联接查询,我的 sql 出了什么问题?

[英]what's wrong in my sql with a simple self-join query?

I have a table comment ,table column as the follow:我有一个表格comment ,表格列如下:

  `comment_id` bigint(20) NOT NULL AUTO_INCREMENT,
  `nick_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
  `comment_content` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT 'content',
  `parent_id` bigint(20) NULL DEFAULT NULL COMMENT 'parentCommentId',
  `active_flag` tinyint(4) NOT NULL DEFAULT 0 COMMENT 'activeFlag',

I have an index on parent_id column, but when I select data using left join on parent_id, the index does not work in. Is there anything wrong?我在 parent_id 列上有一个索引,但是当我在 parent_id 上使用左连接 select 数据时,索引不起作用。有什么问题吗?

The Sql as the follow: Sql 如下:

select * from comment p left join comment sub on p.comment_id = sub.parent_id

The explain result:解释结果:

mysql> EXPLAIN select  * from comment p left join comment sub on p.comment_id = sub.parent_id;
+----+-------------+-------+------------+------+------------------+------+---------+------+--------+----------+----------------------------------------------------+
| id | select_type | table | partitions | type | possible_keys    | key  | key_len | ref  | rows   | filtered | Extra                                              |
+----+-------------+-------+------------+------+------------------+------+---------+------+--------+----------+----------------------------------------------------+
|  1 | SIMPLE      | p     | NULL       | ALL  | NULL             | NULL | NULL    | NULL | 126717 |   100.00 | NULL                                               |
|  1 | SIMPLE      | sub   | NULL       | ALL  | comment_n2 | NULL | NULL    | NULL | 126717 |   100.00 | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+-------+------------+------+------------------+------+---------+------+--------+----------+----------------------------------------------------+
2 rows in set (0.03 sec)

UPDATE:更新:

CREATE TABLE `comment`  (
  `comment_id` bigint(20) NOT NULL AUTO_INCREMENT,
  `catalog_version_code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '',
  `nick_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
  `login_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
  `user_id` bigint(20) NOT NULL COMMENT '',
  `operated_id` bigint(20) NULL DEFAULT NULL COMMENT '',
  `comment_type_code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '',
  `level_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '',
  `comment_content` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '本',
  `average_comment_score` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '',
  `describe_score` int(11) NULL DEFAULT NULL COMMENT '',
  `logistics_score` int(11) NULL DEFAULT NULL COMMENT '',
  `service_score` int(11) NULL DEFAULT NULL COMMENT '',
  `comment_status_code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '',
  `platform_order_code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '',
  `platform_order_entry_code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '',
  `parent_id` bigint(20) NULL DEFAULT NULL COMMENT '',
  `tenant_id` bigint(20) NOT NULL DEFAULT 0,
  `object_version_number` bigint(20) NOT NULL DEFAULT 1,
  `creation_date` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `created_by` bigint(20) NOT NULL DEFAULT -1,
  `last_updated_by` bigint(20) NOT NULL DEFAULT 1,
  `last_update_date` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `reply_flag` tinyint(4) NULL DEFAULT NULL COMMENT '',
  `active_flag` tinyint(4) NOT NULL DEFAULT 0 COMMENT '',
  `display_status` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
  `operated_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
  `platform_product_code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '',
  `platform_sku_code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '',
  `sku_code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '',
  PRIMARY KEY (`comment_id`) USING BTREE,
  UNIQUE INDEX `comment_u1`(`comment_id`, `tenant_id`) USING BTREE,
  INDEX `comment_n1`(`platform_product_code`, `platform_sku_code`, `tenant_id`) USING BTREE,
  INDEX `comment_n2`(`parent_id`, `tenant_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 128596 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '' ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

And there are 126717 records.并且有126717条记录。

There are several possible reasons what an index on parent_id would not be getting used in your query.查询中未使用parent_id上的索引有几个可能的原因。 One reason is that your comment table is fairly small, in which case MySQL might eschew the use of any index and decide to just scan the table.一个原因是您的comment表相当小,在这种情况下 MySQL 可能会避免使用任何索引并决定只扫描表。

Another reason for the index on parent_id not being used is that your query is doing a SELECT * .未使用parent_id索引的另一个原因是您的查询正在执行SELECT * That is, it is selecting all columns from both tables in the query (which happens to be the same table).也就是说,它从查询中的两个表中选择所有列(恰好是同一个表)。 Your index covers the join, but not the select.您的索引涵盖连接,但不包括 select。 You could consider an index which covers all columns:您可以考虑一个涵盖所有列的索引:

CREATE INDEX idx_new ON comment (parent_id, comment_id, comment_content,
                                 nick_name, active_flag);

This index would cover the entire self join to the same table.该索引将覆盖同一张表的整个自连接。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM