【问题标题】:MySQL join performance not using indexMySQL连接性能不使用索引
【发布时间】:2018-11-05 12:25:21
【问题描述】:

新人警告! MariaDB (MySQL) v 10.1.26 出现问题。我有 3 个表:FRIENDS、POSTS 和 USERS。

CREATE TABLE USERS(
  uid INT AUTO_INCREMENT PRIMARY KEY,
  username VARCHAR(40) NOT NULL UNIQUE,
  email VARCHAR(100) NOT NULL UNIQUE, 
  pwhash VARCHAR(200) NOT NULL,
);

CREATE TABLE FRIENDS(
  RID BIGINT AUTO_INCREMENT PRIMARY KEY,
  uid1 INT NOT NULL,                           #user 1 
  uid2 INT NOT NULL,                           #user 2 
  state INT NOT NULL,                          #status from user1 -> user2
  FOREIGN KEY (uid1) REFERENCES USERS(uid),
  FOREIGN KEY (uid2) REFERENCES USERS(uid)
);

CREATE TABLE POSTS(
  pstid BIGINT AUTO_INCREMENT PRIMARY KEY,
  uid INT NOT NULL,
  post_text VARCHAR(500) NOT NULL, 
  time DATETIME DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY(uid) REFERENCES USERS(uid)
);

还有以下表的索引:

CREATE INDEX users_idx1 ON USERS(username);
CREATE INDEX friends_idx1 ON FRIENDS(uid1);
CREATE INDEX friends_idx2 ON FRIENDS(uid2);
CREATE INDEX posts_idx1 ON POSTS(uid);
CREATE INDEX posts_idx2 ON POSTS(time);

我想快速查询朋友最近100个帖子。当前sql:

[EXPLAIN EXTENDED] SELECT * FROM (POSTS as p) 
                   JOIN (FRIENDS as f) ON f.uid2 = p.uid AND 
                                          f.uid1 = ?(userid for current user) 
                                          ORDER BY p.time DESC LIMIT 100;

我的假设是 MySQL 会通过索引获取所有朋友的 uid(f.uid2 其中 f.uid = currentuserid),然后用它搜索帖子,使用 ORDER BY 获取最新的并将结果限制为 100 行。但是,当我运行 EXPLAIN 时:

 id | select_type | table | type | possible_keys                    | key          | key_len | ref             | rows | filtered | Extra
 1  | SIMPLE      | f     | ref  | friends_idx1, friends_idx2, uid2 | friends_idx1 | 4       | const           |  1   | 100.00   | Using temporary; Using filesort
 1  | SIMPLE      | p     | ref  | posts_idx1                       | posts_idx1   | 4       |  friends.f.uid2 |  1   | 100.00   | --

当 p.time、f.uid1 和 f.uid2 被索引时,它说它使用文件排序和临时。欢迎任何有助于提高性能的帮助、解释或建议。提前致谢!

【问题讨论】:

  • 您的测试数据集有多大? (即有多少用户、帖子和友谊?)如果这是小,优化器可能会决定,表扫描比使用这些索引更快。还有其他各种原因,优化器可能不使用索引,但我想说,基数是索引被忽略的最常见原因。
  • 目前数据集非常小,这不是生产环境。有什么方法可以在不创建/获取大量数据集进行测试的情况下测试可扩展性?
  • 我什么都不知道。此外,如果您要创建人工数据(1000 个用户、每个帖子、每个朋友),结果可能再次与“真实数据”不同,其中有 10% 的杰出贡献者和 90% 的临时发帖者。

标签: mysql join database-performance


【解决方案1】:

对于这个查询:

SELECT *
FROM POSTS p JOIN 
     FRIENDS f
     ON f.uid2 = p.uid AND 
        f.uid1 = ?
ORDER BY p.time DESC
LIMIT 100;

此查询的最佳索引很可能是:friends(uid1, uid2)posts(uid)

为什么 MySQL 不使用您的索引?这取决于表统计信息。根据解释,您的表中的数据很少。因此,索引不会产生影响。如果所有数据都适合单个数据页,则索引不太可能影响性能。

【讨论】:

    猜你喜欢
    • 2017-06-27
    • 1970-01-01
    • 1970-01-01
    • 2021-12-20
    • 2011-06-25
    • 2011-01-20
    • 2013-09-10
    • 1970-01-01
    • 2012-07-01
    相关资源
    最近更新 更多