| Kopusha |
|
|---|---|
|
В $db_stories некоторые записи создаються "только для друзей", при этом item_only_friends у них == 1. Есть таблица "с парами друзей", friendid/userid будет пара друзей, если они в "активной" дружбе - со статусом 1. Мне нужно построить выборку в list.stories с зависимостью от того показываем ли мы историю этому конкретному пользователю или нет.
if ($usr['id'])
{
//Get all friends of a user
if (cache_exists('friendlist_'.$usr['id']) && $cfg['apcu_cache'])
{
//получаем id пользователей которые у текущего в друзьях из кеша в виде 1 2 3 4 5
$friends_ids = cache_get('friendlist_'.$usr['id']);
}
if (!isset($friends_ids) || !is_array($friends_ids))
{
global $db_cot_social_friendslist, $db_x;
$db_cot_social_friendslist = (isset($db_cot_social_friendslist)) ? $db_cot_social_friendslist : $db_x . 'social_friendslist';
//если в кеше их нет то получаем их из БД
$friends_ids = $db->query("
SELECT
CASE
WHEN userid = :userid THEN friendid
ELSE userid
END AS friend_id
FROM $db_cot_social_friendslist
WHERE status = 1
AND (userid = :userid OR friendid = :userid)
", [':userid' => $usr['id']])->fetchAll(PDO::FETCH_COLUMN) ?: [];
$friends_ids = array_unique($friends_ids);
if(!empty($friends_ids))
{
if($cfg['apcu_cache'])
{
cache_store('friendlist_'.$usr['id'], $friends_ids, 3200);
}
}
}
//если пользователь не администратор
if (!$usr['isadmin'])
{
if (empty($friends_ids)) {
//и у него нет друзей - не показываем истории которые только для друзей
$where_friends = "AND (item_only_friends=0 OR item_userid=".$usr['id'].")";
} else {
//и у него есть друзья то показываем истории что для всех, которые его и которые для друзей и в списке его друзей есть автор истории
$where_friends = "AND (item_only_friends=0 OR item_userid=".$usr['id']." OR item_userid IN (".implode(',', array_map('intval', $friends_ids))."))";
}
}
}
else
{
$where_friends = "AND (item_only_friends=0)";
}
$totalitems = $db->query("SELECT COUNT(*) FROM $db_stories AS f
$join_condition
LEFT JOIN $db_users AS u ON u.user_id=f.item_userid
" . $where . "
$where_condition
$where_friends
")->fetchColumn();
//и выборка самих историй по такому же принципу
$sqllist = $db->query("SELECT f.*, u.* $join_columns
FROM $db_stories AS f $join_condition
LEFT JOIN $db_users AS u ON u.user_id=f.item_userid
" . $where . "
$where_condition
$where_friends
" . $order . "
LIMIT $d, " . $maxrowsperpage); //$maxrowsperpage = 30
$sqllist_rowset = $sqllist->fetchAll();
$sqllistcount = $sqllist->rowCount();
По сути мой вопрос в чем - если friends_ids будет сотни и тысячи значений, не станут ли запросы в БД слишко тяжелыми и как лучше поступить в такой ситуации? Added 56 seconds later: собственно беспокойство вызывает Added 5 minutes later: PS item_userid для db_stories Композитный индекс для userid, friendid, status в таблице $db_cot_social_friendslist так же есть
Відредаговано: Kopusha (17.02.2025 09:32, 8 місяців тому) |
| Kort |
|
|---|---|
|
Самое простое -- закэшировать результат на разумный срок SED.by - создание сайтов, разработка плагинов и тем для Котонти
|
| Kopusha |
|
|---|---|
|
для каждого конкретного пользователя? для юзера 1 одни списки для юзера 2 (у него другой список друзей) другие и тд и это выборка первых 30 записей, после почти сразу +30 инфинитскроллом и так далее Added 1 minute later: пробую так
$db->exec("
CREATE TEMPORARY TABLE temp_friends (
friend_id INT PRIMARY KEY
) ENGINE=MEMORY;
");
if (!empty($friends_ids)) {
$placeholders = implode(',', array_fill(0, count($friends_ids), '?'));
$stmt = $db->prepare("INSERT INTO temp_friends (friend_id) VALUES ($placeholders)");
$stmt->execute($friends_ids);
}
// Запрос с временной таблицей
$totalitems = $db->query("SELECT COUNT(*)
FROM $db_stories AS f
LEFT JOIN $db_users AS u ON u.user_id=f.item_userid
LEFT JOIN temp_friends tf ON tf.friend_id = f.item_userid
$join_condition
" . $where . "
$where_condition
$where_friends
")->fetchColumn();
$db->exec("DROP TEMPORARY TABLE IF EXISTS temp_friends;");
|