У меня есть общая таблица 1629664 в таблице users
.
Если я использую SELECT count(u.id) FROM users
он возвращает результат в течение 0.00053
секунды, это хорошо !!!
Если я собираюсь SELECT count(u.id) FROM users u INNER JOIN user_profile p ON p.user_id = u.id and p.is_delete = 0
к SELECT count(u.id) FROM users u INNER JOIN user_profile p ON p.user_id = u.id and p.is_delete = 0
он возвращает результат в пределах 5.67 или более секунд, что не подходит для меня, как мы можем оптимизировать этот?
Кроме того, если я добавлю больше столбца, where
с запросом
SELECT count(u.id)
FROM 'users' 'u'
INNER JOIN 'user_profile' 'p' ON 'p'.'user_id' = 'u'.'id'
and 'p'.'is_delete' = 0
WHERE 'u'.'gender' in (1,0)
AND 'u'.'status' = 1
AND 'u'.'is_delete' =0
AND 'u'.'user_role' = 2
AND 'u'.'id' <> 5720962
AND 'u'.'search_n_dashboard' = 'visible'
он возвращает результат в течение 12.45 или более секунд, мне нужно оптимизировать этот.
Я использовал индексирование пользователей CREATE INDEX users_index ON users (id); CREATE INDEX user_profile_index ON user_profile (user_id);
CREATE INDEX users_index ON users (id); CREATE INDEX user_profile_index ON user_profile (user_id);
Пожалуйста, предложите мне, как я могу оптимизировать больше?
Заранее спасибо!!!
глядя на вас и где вы можете использовать составной индекс
On table users ( gender , id , status, is_delete , user_role ,id , search_n_dashboard)
а также
On table user_profile ( is_delete ,user_id )
на основе этого индекса вы можете попробовать инвертировать таблицы (изменить таблицу команд), а также избежать предложения IN, используя INNER ON subselect
SELECT count(u.id)
FROM 'user_profile' 'p'
INNER JOIN 'users' 'u' ON 'p'.'user_id' = 'u'.'id' and 'p'.'is_delete' = 0
INNER JOIN ( select 1 as gender union select 2 ) T on T.gender = u.gender
WHERE 'u'.'status' = 1
AND 'u'.'is_delete' =0
AND 'u'.'user_role' = 2
AND 'u'.'id' <> 5720962
AND 'u'.'search_n_dashboard' = 'visible'
а также вы можете использовать FORCE индекс для соединения
SELECT count(u.id)
FROM 'user_profile' 'p'
INNER JOIN 'users' 'u' FORCE INDEX FOR JOIN ('your_index_for_join') ON 'p'.'user_id' = 'u'.'id' and 'p'.'is_delete' = 0
INNER JOIN ( select 1 as gender union select 2 ) T on T.gender = u.gender
WHERE 'u'.'status' = 1
AND 'u'.'is_delete' =0
AND 'u'.'user_role' = 2
AND 'u'.'id' <> 5720962
AND 'u'.'search_n_dashboard' = 'visible'
Имейте эти индексы:
u: (status, is_delete, user_role, search_n_dashboard, gender) -- 'gender' last
p: (user_id, is_delete) -- in either order
Не говорите COUNT(x)
если вам не нужно проверять x
наличие NULL
; просто скажите COUNT(*)
.
0.00053s является фиктивным - вы включили кеш запросов. Повторите запросы таким образом:
SELECT SQL_NO_CACHE ...
чтобы избежать контроля качества.
Для ясности для читателя используйте ON
чтобы сказать, как связаны таблицы, а не для фильтрации. Это перемещение p.is_delete = 0
в WHERE
.
Не is_delete
ли is_delete
status
и is_delete
в один столбец?
Сколько у вас "полов"? Если у вас всего 2, то избавитесь от теста; что у вас затрудняет оптимизацию.
Подробнее о написании индексов: http://mysql.rjweb.org/doc.php/index_cookbook_mysql
Предположительно, u.id
уникален. Следовательно, вы можете упростить свой запрос:
SELECT count(*)
FROM user_profile p
WHERE p.is_delete = 0;
Этот запрос может воспользоваться индексом user_profile(is_delete)
.