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 так же есть
|
|
Dit bericht is bewerkt door Kopusha (2025-02-17 09:32, 4 maanden ago) |
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;");
|