SQL查询性能问题全表扫描

时间:2014-11-17 21:33:36

标签: mysql sql

我有一个触发下面sql的脚本。直到现在,这个查询的表现还不算太糟糕,我相信这是因为其中一个表中存在大量记录,而且根据我在运行的说明在查询中,它对整个用户表执行扫描(大约1000万条记录)。

有没有更好的方法来编写它,以便它不会扫描,我可以将执行返回到< 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))))

****更新**** 我相信我已经孤立,或者至少缩小了问题的来源。

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 :(得分:1)

首先,您应该考虑在子查询中使用JOIN。除非您有充分的理由使用子查询,否则这本身应该会向您显示性能的改进。我无法想象一个阻止你使用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()子查询。如果users表和user_board之间的关系是1:many

,则此查询应该是一个短而快的电路。
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);

如果这没有帮助,您应该考虑为用户和users_boards发布show create table我想相信您的列类型不同。

SHOW CREATE TABLE users;
SHOW CREATE TABLE users_board;