Производительность соединения MySQL без индекса - PullRequest
0 голосов
/ 05 ноября 2018

Предупреждение для новичков! Проблема с MariaDB (MySQL) v 10.1.26. У меня есть 3 таблицы: ДРУЗЬЯ, ПОСТЫ и ПОЛЬЗОВАТЕЛИ.

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 получит все идентификаторы друзей (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 проиндексированы. Любая помощь, объяснения или предложения по повышению производительности приветствуются. Заранее спасибо!

1 Ответ

0 голосов
/ 05 ноября 2018

Для этого запроса:

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 не использует ваши индексы? Это зависит от статистики таблицы. Согласно объяснению, у вас очень мало данных в ваших таблицах. Следовательно, индексы не будут иметь значения. Если все данные помещаются на одной странице данных, индекс вряд ли повлияет на производительность.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...