简体   繁体   English

SQL查询性能问题全表扫描

[英]SQL query performance issue full table scan

I have a script that triggers the below sql . 我有一个触发以下sql的脚本。 The performance of this query wasn't too bad until now, and I believe it's because of the large number of records that exist in one of the tables and, according to the explain I'm running on the query, it's performing a scan against the entire users table (approx 10 million records). 到目前为止,该查询的性能还不错,我相信这是因为其中一个表中存在大量记录,并且根据我正在查询中运行的解释,它正在针对该表进行扫描整个用户表(大约一千万条记录)。

Is there a better way to write this so that it doesn't scan and I can get the executions back down to < 1 second? 有没有更好的方法可以编写此代码,使其不扫描,并且我可以将执行时间降低到<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 **** I believe I've isolated, or at least narrowed down where the issue is coming from. ****更新****我相信我已经隔离,或者至少缩小了问题的出处。

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

EXPLAIN on the query gives the following: 对查询的解释给出以下内容:

# 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)

First of all, you should consider using JOIN over the sub queries. 首先,您应该考虑在子查询上使用JOIN。 This by itself should show you improvement in performance unless you have a super good reason to use sub query. 除非您有充分的理由使用子查询,否则这本身应该显示出性能的提高。 I can't imagine a good reason that would stop you from using JOINS. 我无法想象有一个很好的理由会阻止您使用JOINS。

Now, that you identified the query that is causing you to loose performance. 现在,您确定了导致性能下降的查询。 Let's try to tune it. 让我们尝试对其进行调整。

Try both of theses queries as they should help you improve the speed. 尝试这两个查询,因为它们应该可以帮助您提高速度。

1 Join Query if the relation between users and users_board is 1:1 and you are looking to display all results 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() sub query. 2个EXISTS()子查询。 This query should be a short and fast Circuit if the relation between the users table and the user_board is 1:many 如果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 you can try using Temporary Tables just before any query I listed above to see if there is any improvement. 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;

Also this index should be very helpful. 同样,该索引应该非常有帮助。 If you can add it (if it does not exists) you should consider it 如果可以添加(如果不存在),则应考虑

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

If this does not help you should consider posting your show create table for users and for users_boards I would like to believe that your column types are not the same. 如果这样做没有帮助,您应该考虑为用户和users_boards发布show create table ,我想您的列类型是不同的。

SHOW CREATE TABLE users;
SHOW CREATE TABLE users_board;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM