2014-11-17 4 views
1

У меня есть скрипт, который запускает ниже sql. Производительность этого запроса не так уж плоха до сих пор, и я считаю, что это из-за большого количества записей, которые существуют в одной из таблиц, и, согласно объяснению, которое я выполняю в запросе, оно выполняет проверку против таблица всех пользователей (около 10 миллионов записей).Ошибка выполнения SQL-запроса Полное сканирование таблицы

Есть ли лучший способ написать это, чтобы он не сканировал, и я могу получить выполнение до < 1 секунда?

SELECT 
`users` . *, 
users.username AS `fullname`, 
(SELECT 
     CONCAT_WS('|||', 
        image, 
        width, 
        height, 
        original, 
        mime) 
    FROM 
     `users_avatars` 
    WHERE 
     (user_id = users.user_id) 
      AND (size = '_A') 
    LIMIT 1) AS `user_avatar_a`, 
(SELECT 
     CONCAT_WS('|||', 
        image, 
        width, 
        height, 
        original, 
        mime) 
    FROM 
     `users_avatars` 
    WHERE 
     (user_id = users.user_id) 
      AND (size = '_B') 
    LIMIT 1) AS `user_avatar_b`, 
(SELECT 
     CONCAT_WS('|||', 
        image, 
        width, 
        height, 
        original, 
        mime) 
    FROM 
     `users_avatars` 
    WHERE 
     (user_id = users.user_id) 
      AND (size = '_C') 
    LIMIT 1) AS `user_avatar_c`, 
((SELECT 
     COUNT(ufu_id) 
    FROM 
     `users_following_user` 
    WHERE 
     (user_id = 684767) 
      AND (following_id = users.user_id) 
    LIMIT 1) + (SELECT 
     COUNT(users_following_id) 
    FROM 
     `users_following` 
    WHERE 
     (user_id = 684767) 
      AND (following_id = users.user_id) 
    LIMIT 1)) AS `following_user` 
FROM 
`users` 
WHERE 
(users.user_id IN ((SELECT 
     `users_boards`.`user_id` 
    FROM 
     `users_boards` 
    WHERE 
     (board_id = '353048') AND (allow = 1)))) 

**** **** UPDATE Я считаю, что я изолирован, или по крайней мере сужен, где проблема происходит из.

SELECT * 
FROM 
    `users` 
WHERE 
    (users.user_id IN ((SELECT 
     `users_boards`.`user_id` 
    FROM 
     `users_boards` 
    WHERE 
     (board_id = '353048') AND (allow = 1)))) 

EXPLAIN на запрос дает следующее:

# id, select_type, table, type, possible_keys, key, key_len, ref, rows, filtered, Extra 
1, PRIMARY, users, ALL, PRIMARY, , , , 3952473, 100.00, 
1, PRIMARY, users_boards, ref, user_id, user_id, 16, skoovy_prd.users.user_id,const, 1, 100.00, Using where; FirstMatch(users) 
+1

Какой стол большой мальчик –

+0

Вы можете проверить EXPLAIN EXTENDED из каждого суб запроса, чтобы выяснить, какой из них является медленный запрос? Кроме того, попытались ли вы создать временную таблицу для вспомогательных запросов? – Jaylen

+0

Есть ли веская причина использовать подзапросы вместо соединений? Сколько номеров идентификаторов пользователей находится в users_boards? –

ответ

1

Прежде всего, следует рассмотреть возможность использования РЕГИСТРИРУЙТЕСЬ над подразделам запросов. Это само по себе должно показать вам улучшение производительности, если у вас нет веской причины использовать дополнительный запрос. Я не могу представить себе вескую причину, которая помешала бы вам использовать JOINS.

Теперь вы определили запрос, который приводит к потере производительности. Попробуем настроить его.

Попробуйте оба эти вопроса, так как они помогут вам улучшить скорость.

1 Регистрация запроса, если соотношение между пользователями и users_board составляет 1: 1, и вы хотите отобразить все результаты

SELECT su.* FROM users AS su 
INNER JOIN users_boards AS b ON b.user_id = su.user_id 
WHERE b.board_id = 353048 AND b.allow = 1 

2 EXISTS) под запрос (. Этот запрос должен быть коротким и быстрым Circuit, если соотношение между таблицей пользователей и user_board составляет 1: многие

SELECT * 
FROM users AS su 
WHERE EXISTS (SELECT 1 FROM users_boards WHERE user_id = su.user_id AND board_id = 353048 AND allow = 1) 

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

CREATE TEMPORARY TABLE users_boards (KEY(user_id)) ENGINE=MEMORY AS 
SELECT user_id 
FROM users_boards 
WHERE user_id = su.user_id AND board_id = 353048 AND allow = 1; 

Также этот показатель должен быть очень полезным. Если вы можете добавить его (если она не существует), вы должны рассмотреть его

ALTER TABLE users_boards ADD INDEX combo (user_id, board_id, allow); 

Если это не поможет, вы должны рассмотреть размещение вашей show create table для пользователей и users_boards Я хотел бы верить, что ваши типы столбцов не являются тоже самое.

SHOW CREATE TABLE users; 
SHOW CREATE TABLE users_board; 
+0

Спасибо, Майк. Я изменил запрос, чтобы использовать номер 1 и номер 2, и ТАКЖЕ обнаружил, что на board_id нет индекса, разрешите в таблице users_boards !!! – kambythet

+0

время выполнения сейчас.12 секунд – kambythet

+0

@kambythet Я рад, что это сработало для вас :) Я немного пересмотрел свой ответ, вам следует рассмотреть предложение, которое я оставил для вас по поводу запросов. – Jaylen

Смежные вопросы