Повышение производительности и удобство использования Facebook FQL
Я пытаюсь получить некоторые идеи со страниц, на которых я являюсь администратором Facebook.
Что делает мой код, он получает идентификаторы страниц, с которыми я хочу работать через mySQL. Однако я не включил эту часть.
После этого я получаю page_id, имя и fan_count каждого из этих идентификаторов facebook и сохраняются в fancounts[]
.
У меня есть две проблемы.
- Он имеет очень низкую производительность
- Я не могу найти способ повторить эти данные следующим образом:
Мои вопросы: как можно изменить код для повышения производительности и показать данные, как указано выше? Я читал о fql.multiquery. Может ли он использоваться здесь?
Пожалуйста, предоставьте мне примеры кода. Спасибо вам
Ответы
Ответ 1
Если у вас n
страницы, ваш script выполняет запросы n+1
. Это главный недостаток вашего script. Это является причиной низкой производительности.
Вы можете использовать пакетный запрос для объединения запросов. Вы можете использовать ниже script для достижения желаемого. Я объединил эти запросы n+1
только с одним пакетным запросом. Таким образом, он будет медленнее, чем ваш script.
Я также исправил часть echo
. Теперь script отобразит результат, как вы указали в своем вопросе.
// Get the IDs
$pages = array();
$pagesIds = implode(',', $pages);
// fancounts[] holds the page_id, name and fan_count of the Ids I work with
$fancounts = array();
$q = "SELECT page_id, name, fan_count FROM page WHERE page_id IN ({$pagesIds})";
$queries[] = array('method'=>'GET', 'relative_url' => 'method/fql.query?query=' . urlencode($q) );
$messages = array();
foreach( $pages as $id)
{
$q = "SELECT message FROM stream WHERE source_id = '$id' LIMIT 2";
$queries[] = array('method'=>'GET', 'relative_url' => 'method/fql.query?query=' . urlencode($q) );
}
// The batch query
$batchResponse = $facebook->api('?batch='.json_encode($queries), 'POST');
$pagesFanCounts = json_decode($batchResponse[0]['body'], TRUE);
foreach ($pagesFanCounts as $page)
{
$fancounts[] = number_format($page['page_id'],0,'','')."-".$page['name']."-".$page['fan_count'];
}
for($i=0; $i < count($fancounts); $i++)
{
echo '</br>',$fancounts[$i],'<br>';
$temp = json_decode($batchResponse[$i+1]['body'], TRUE);
foreach ($temp as $msg)
{
echo ($msg['message']);
echo "</br>";
}
}
Ответ 2
В настоящий момент вы делаете два отдельных обращения к базе данных Facebook, которые замедляют все. Facebook предлагает свои мультикварки, чтобы вы могли делать все как можно меньше звонков БД. Таким образом, вы должны подумать об использовании:
"query1":"SELECT page_id, name, fan_count FROM page WHERE page_id IN ($pagesIds)"
И поскольку они позволяют ссылаться на предыдущий запрос, вы можете просто включить его после #:
"query2":"SELECT message FROM stream WHERE source_id IN (SELECT page_id FROM #pages) LIMIT 2"
PHP, который вам нужно использовать, выглядит примерно так:
$query = array(
"pages"=>"SELECT page_id, name, fan_count FROM page WHERE page_id IN ($pagesIds)",
"messages"=>"SELECT message FROM stream WHERE source_id IN (SELECT page_id FROM #pages) LIMIT 2"
);
$fql_url = $facebook->api(array(
'method' => 'fql.multiquery',
'queries' => $query
));
print_r($fql_url);
Если второй запрос не проходит, попробуйте протестировать FB DB только с этим запросом и посмотреть, работает ли он. Если запрос ничего не возвращает сам по себе, проблема может заключаться в разрешении (т.е. В доступе к чувствительной таблице, но я не думаю, что это так). Еще одна проблема, с которой я часто сталкиваюсь, заключается в том, как FQL запускается с пробелами, поэтому попробуйте исключить все возможные пробелы из вашего массива:
$query = array("pages"=>"SELECT page_id, name, fan_count FROM page WHERE page_id IN ($pagesIds)","messages"=>"SELECT message FROM stream WHERE source_id IN (SELECT page_id FROM #pages) LIMIT 2");
Ничего себе, этот читаемый...
Это было взято из документации по Facebook на FQL, поэтому, возможно, вам придется адаптировать его для своего веб-приложения, если вы используете стороннюю библиотеку. Все ваши данные сохраняются в $fql_url
. Все, что вам нужно сделать, - это пройти через него и отобразить нужную вам информацию. Если вы хотите увидеть резюме всего, что он содержит, подумайте об использовании print_r()
или var_dump()
только для того, чтобы понять.
ИЗМЕНИТЬ
Причина, по которой вы получаете пустой массив для второго запроса, состоит в том, что у вас нет прав для таблицы stream
. Если вы проверите Facebook документацию, они упомянули критерии, необходимые для доступа к этой таблице:
Чтобы прочитать таблицу потоков, вам нужно
-
read_stream
разрешений для всех сообщений, которые текущий пользователь сеанса возможность просмотра -
read_insights
разрешений на просмотр сообщений для любых сообщений, сделанных страницей, принадлежащей текущему пользователю сеанса.
Чтобы проверить, какие разрешения у вас есть, вы можете запустить этот запрос:
$check_query = $facebook->api(array(
"method" => "fql.query",
"query" => "SELECT * FROM permissions WHERE uid=me()"
));
foreach($check_query[0] as $k => $v) {
if($v === "1") {
echo "<strong>$k</strong> permission is granted.<br>";
} else {
echo "<strong>$k</strong> permission is not granted.<br>";
}
}
Ответ 3
Вы можете попробовать что угодно, но ваш код не будет работать быстро, потому что вы нарушаете золотое правило высокоскоростного веб-приложения. Теперь вы написали:
request1->(wait for response-> download data) -> request2 (wait for response ->
download data) -> and so on ......
И что вы должны действительно делать: -
request1->(wait for response-> download data)
request2->(wait for response-> download data)
request3->(wait for response-> download data)
......
......
Да, вы должны сделать сразу несколько запросов, чтобы уменьшить общее время отклика. Браузер ускоряет загрузку страницы только этим способом.
Я столкнулся с подобной проблемой во время работы над фидером RSS-канала (у него огромная база данных RSS-ссылок).
Чтобы решить эту проблему, я могу предложить вам две вещи.
-
Используйте команду multi-curl для извлечения нескольких команд одновременно. Это действительно ускорит ваш script, поскольку сразу несколько запросов уменьшат общее время.
-
Но выше решение будет работать в некоторой степени. Если вы запрашиваете много данных, вам нужно искать в другом месте, поскольку php не поддерживает многопоточность. Вы можете использовать java или node.js в качестве альтернативы и использовать redis-сервер (не недооценивайте его) как конвейер между PHP скрипт и java или node.js, используя его pub/sub facility. По моему мнению, это лучшая альтернатива, и я использовал ее для сбора более сотни тысяч записей, и она никогда не терпит неудачу.
И другое, в чем я не могу вам помочь, это скорость вашего интернет-соединения;)
Надеюсь, что это решает вашу проблему:)
Дипак