Левое соединение таблицы B с таблицей A происходит мгновенно, когда B имеет совпадения с A, но занимает вечность (> 1 минуты), когда совпадений нет. Почему это? - PullRequest
0 голосов
/ 06 августа 2020

Я хочу:

SELECT T.TournamentId, Sum(Score) as Score
FROM Tournament T
    LEFT JOIN Scores S on S.TournamentId = T.TournamentId
WHERE T.TournamentId = x
GROUP BY T.TournamentId

Когда я выбираю TounamentId «x» в предложении WHERE, которое еще не началось, выполнение запроса занимает вечность. Когда я выбираю «x» для начавшегося турнира, он запускается мгновенно.

Настоящий запрос немного сложнее этого. Но это root проблема. Почему это могло произойти и что я могу сделать, чтобы это ускорить? Я хотел бы иметь возможность использовать один и тот же запрос для обоих случаев. Но если я ничего не могу сделать, я создам второй запрос, который будет запускаться, когда турнир еще не начался.

1 Ответ

0 голосов
/ 06 августа 2020

Если какая-либо из таблиц очень большая, эта проблема имеет смысл, и в этом случае вы должны попытаться ограничить ее как можно больше (некоторые люди утверждают, что сервер сделает это сам, но это не так. time).

Попробуйте, например,

SELECT
    T.TournamentId, SUM(Score) AS Score
FROM 
    Tournament T
LEFT JOIN 
    Scores S ON S.TournamentId = T.TournamentId AND S.TournamentId = x
WHERE 
    T.TournamentId = x
GROUP BY 
    T.TournamentId

В противном случае вы можете написать хранимую процедуру и создать временную таблицу, которая является копией S, но содержит только строки, где TournamentId = x. Объединения всегда тяжелы для баз данных, и уменьшение размеров таблиц перед их использованием в объединении может ускорить работу на миллионы процентов.

Как уже указывалось, вы также можете использовать индекс для ускорения, в этом случае требуется индекс чтобы соответствовать значениям, к которым вы присоединяетесь, вам также следует подумать о регулярном пересоздании индекса (легко в ms sql, PAIN в mysql). А чтобы еще больше ускорить процесс, вы можете добавить пользовательские индексы к своим временным таблицам, особенно если у вас много огромных таблиц, это значительно ускорит работу, если влияние нескольких сотен / тысяч строк будет незначительным или даже отрицательным ..

# Make sure the tables are not already there
DROP TEMPORARY TABLE IF EXISTS tmp_Tournament;
DROP TEMPORARY TABLE IF EXISTS tmp_Scores;

CREATE TEMPORARY TABLE tmp_Tournament
SELECT * from Tournament WHERE TournamentId = x;
CREATE INDEX tmp_Tournament_TournamentId ON tmp_Tournament (TournamentId);
CREATE TEMPORARY TABLE tmp_Scores
SELECT * FROM Scores WHERE TournamentId = x;
CREATE INDEX tmp_Scores_TournamentId ON tmp_Scores (TournamentId);

SELECT
    T.TournamentId, SUM(Score) AS Score
FROM 
    tmp_Tournament T
LEFT JOIN 
    tmp_Scores S ON S.TournamentId = T.TournamentId AND S.TournamentId = x
WHERE 
    T.TournamentId = x
GROUP BY 
    T.TournamentId;

# Just some cleanup
DROP TEMPORARY TABLE IF EXISTS tmp_Tournament;
DROP TEMPORARY TABLE IF EXISTS tmp_Scores;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...