2015-02-13 2 views
0

У меня есть сайт с более 1'000'000 ежедневным просмотром страницы и PHP скриптом для отображения 2-3 баннеров на каждой странице и сосчитать впечатленияОптимизировать PHP/MySQL скрипт для уменьшения использования сервера

К подсчет показов, после каждого баннера есть изображение:

<img src="https://example.com/impression.php?client=ABC&banner=XYZ" width=1 height=1>

Это пример слепка сценария:

require('global.php'); // connect to mysql, read default settings, etc 

if(isset($_GET['client'])) && !empty($_GET['client'])) { $client = secure($_GET['client']); } else { die('error param'); } 
if(isset($_GET['banner'])) && !empty($_GET['banner'])) { $banner = secure($_GET['banner']); } else { die('error param'); } 

$check_client = mysqli_query($con, "SELECT id FROM clients WHERE id = '$client' AND status = 1 LIMIT 1") or die('error mysql'); 
if(mysqli_num_rows($check_client) == 0) { die('error client'); } 

$check_banner = mysqli_query($con, "SELECT campaign_id FROM banners WHERE id = '$banner' AND status = 1 LIMIT 1") or die('error mysql'); 
if(mysqli_num_rows($check_banner) == 0) { die('error banner'); }  
$read_campaign_id = mysqli_fetch_array($check_banner); 

$check_campaign = mysqli_query($con, "SELECT id FROM campaigns WHERE id = '$read_campaign_id[0]' AND status = 1 LIMIT 1") or die('error mysql'); 
if(mysqli_num_rows($check_campaign) == 0) { die('error campaign'); } 

$check_unique = mysqli_query($con, "SELECT id FROM impressions WHERE datetime LIKE '$today%' AND banner = '$banner' AND ip = '$ip' ORDER BY datetime DESC LIMIT 1") or die('error mysql'); 
if(mysqli_num_rows($check_unique) == 1) { $unique = 0; } else { $unique = 1; } 

mysqli_query($con, "INSERT INTO impressions (client, campaign, banner, datetime, unique, ip, page) VALUES ('$client', '$read_campaign_id[0]', '$banner', '$now', '$unique', '$ip', '$url')") or die('error mysql'); 

header('Content-type: image/png'); 
header($path . '/img/pixel.png'); 
mysqli_close($con); 
exit; 

В этом случае лучший способ для оптимизации сценария и сокращения использования ресурсов и одновременных подключений на моем сервере?

  • Например, возможно ли подключиться к некоторому запросу mysql в одном запросе? Я думаю, это должно быть намного быстрее, но я не уверен ...
  • Еще один возможный способ - сохранить показы в CSV-файле, и каждые 2-5 минут импортировать этот файл в mysql? но это только сохранить 1 запрос ...

EDIT: Это структура MySQL таблицы (только с полезными полями для данного примера) http://sqlfiddle.com/#!2/1ffe3/1

+2

Сначала убедитесь, что все ваши запросы MySQL оптимизированы. Проверьте их с помощью запросов 'EXPLAIN'. –

+0

Какие индексы у вас есть в таблице показов в частности? –

+0

@Mark Baker: все колонки ** id ** являются первичными. ** datetime ** (в таблице показаний) - это индекс. ** campaign_id ** в таблице баннеров и ** клиент, кампания, баннер ** в таблице показов имеют внешние ограничения на обновление, поэтому я думаю, что они автоматически индексируются. – ipel

ответ

1

Да, вы можете запустить все выбирает в одном запросе.

Довольно смутно (поскольку вам требуется только одна строка от каждого, и между ними нет очевидной связи), вы можете сделать это с помощью декартова продукта.

Ваша схема отстой (WHERE DATETIME LIKE «$ сегодня%», используя строку для хранения даты !!!!)

Почему вы приказывая результат $ check_unique, когда вы только хотите, чтобы увидеть, если какой-либо строки существует?

SELECT clients.id AS client_id 
, banner.campaign_id AS banner_campaign_id 
, campaign_id 
,(SELECT COUNT(*) 
    FROM impressions 
    WHERE impressions.datetime LIKE '$today%' 
    AND impressions.banner = '$banner' 
    AND ip = '$ip' 
    LIMIT 1) AS check_unique 
FROM clients 
INNER JOIN banners 
INNER JOIN campaigns 
WHERE clients.id = '$client' AND clients.status = 1 
AND banners.id = '$banner' AND banners.status = 1 
AND campaigns.id = '$read_campaign_id[0]' AND campaigns.status = 1 
LIMIT 1 

В качестве альтернативы вы можете развернуть его в UNION, но это гораздо менее интересно.

+0

Thx! Столбец «datetime» - это тип datetime 'datetime datetime NOT NULL', почему он сосет? Я использую 'ORDER BY datetime DESC', потому что проверка $ сегодня, чтобы избежать того, что mysql читает старые записи, не лучше? – ipel

+0

Тогда ваш запрос сосет - должна быть операция диапазона с любым неявным литом на литералы. – symcbean