【问题标题】:Optimize SQL query on two tables优化两个表的 SQL 查询
【发布时间】:2021-12-08 11:17:07
【问题描述】:

我对有很多行的表有一个 SQL 查询。所以这个查询运行了很长时间。如何优化此查询? 这些表已经在 id 和friend_id 上有索引

SELECT u.id, u.first, u.last, 
  group_concat(u2.first, " " , u2.last) MyFriends 
  FROM Users u
  INNER JOIN Friends f ON f.user_id = u.id 
  INNER JOIN Users u2 ON u2.id = f.friend_id
  GROUP BY u.id;

这些是表结构:

CREATE TABLE Users ( 
  id int(10) unsigned NOT NULL, 
  first varchar(50) DEFAULT NULL, 
  last varchar(50) DEFAULT NULL, 
  city varchar(20) DEFAULT NULL, 
  country varchar(20) DEFAULT NULL, 
  Age tinyint(3) unsigned NOT NULL, 
  KEY users_idx_id (id)) 
ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE Friends ( 
  user_id int(10) unsigned NOT NULL, 
  friend_id int(10) unsigned NOT NULL, 
  KEY idx_friends (friend_id)) 
ENGINE=InnoDB DEFAULT CHARSET=latin1;

【问题讨论】:

标签: mysql sql query-optimization


【解决方案1】:

多对多映射表 (Friends) 需要改进索引。删除您现在拥有的所有索引并添加

PRIMARY KEY(user_id, friend_id),
INDEX(friend_id, user_id)

更多讨论:http://mysql.rjweb.org/doc.php/index_cookbook_mysql#many_to_many_mapping_table

Age 是一个移动的目标。想一个更好的方法来存储它。

大约有 6 个国家的名字超过 20 个。“圣文森特和格林纳丁斯”是 32 个。

对于城市,“Poselok Uchebnogo Khozyaystva Srednego Professionalno-Tekhnicheskoye Uchilishche Nomer Odin”为 91 个字符。

ALTER TABLE Friends
    DROP INDEX idx_friends,
    ADD PRIMARY KEY(user_id, friend_id),
    ADD INDEX(friend_id, user_id);

每个表都应该有一个PRIMARY KEY:

ALTER TABLE Users
    DROP INDEX users_idx_id,
    ADD PRIMARY KEY(user_id)

了解AUTO_INCREMENT

“执行计划”可以通过运行EXPLAIN SELECT ... 来获得。但是它不会提供很多线索在这种情况下

【讨论】:

  • 那是我唯一需要做的改变吗?
  • 添加它们的命令是什么?
  • @Max - 我确信它会加快查询速度。如果不够满足,则为每个表提供EXPLAIN SELECT ...SHOW CREATE TABLE。还要指定表中有多少行。 (有许多不太常见的事情可能会导致性能问题。)
  • @Max - 我必须看到SHOW CREATE TABLE,所以我还可以指定如何删除现有索引。
  • @Max - 我加了一堆。
猜你喜欢
  • 2015-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-15
  • 2016-12-08
  • 2016-10-16
相关资源
最近更新 更多