我有一个触发下面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)
答案 0 :(得分:1)
首先,您应该考虑在子查询中使用JOIN。除非您有充分的理由使用子查询,否则这本身应该会向您显示性能的改进。我无法想象一个阻止你使用JOINS的好理由。
现在,您确定了导致性能下降的查询。我们试着调整它。
尝试这两种查询,因为它们可以帮助您提高速度。
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
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)
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;