2008-12-03 3 views
1

Хорошо, моя дилемма такова. У меня есть страница администратора, которую я использую, чтобы получить сводку материалов дня на одном из моих сайтов. Эта страница sumamry извлекает данные из нескольких таблиц, некоторые из которых хранят фактические данные мультимедиа, другие хранят URL-адреса, идентификаторы и владельцы веб-сайта, а другая таблица хранит ежедневную статистику для расчета коэффициентов ввода/вывода для каждого домена.Возможно ли слияние этих (длинных) запросов mysql?

Эта страница админ имеет основной запрос, который вытягивает фактические данные СМИ, который выглядит следующим образом (упрощенный):

SELECT 
    content.con_catid, 
    content.con_posttime, 
    content.con_url, 
    content.con_id, 
    content.con_title, 
    categories.name, 
    users.username, 
    users.user_id, 
     FROM content 
     LEFT JOIN categories 
     ON (content.con_catid = categories.id) 
     LEFT JOIN users 
     ON (content.con_poster = users.user_id) 
     WHERE con_status = 0 ORDER BY con_posttime 

довольно прямо вперед. Тогда, это - то, где это становится беспорядочным. Для каждого времени петель заявления mysql_fetch_array (для вывода каждого элемента контента), я также запустить эти 2 запросов:

SELECT count(con_id) as pending FROM content WHERE con_poster = '$this_userid' AND con_status = 0 

SELECT count(con_id) as approved FROM content WHERE con_poster = '$this_userid' AND con_status = 2 

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

И тогда есть убийца, который добавляет много времени, чтобы время выполнения страницы, так как он также должен быть повторен для каждой строки исходного запроса.

SELECT website_url, 
website_id, 
website_shady, 
COALESCE(sum(dstats_hits),0)+website_in_ballast as total_in, 
COALESCE(sum(dstats_hits_out),0)+website_out_ballast as total_out, 
sum(dstats_hits_out_paid) as total_paid, 
website_in_ballast, 
website_out_ballast 
    FROM websites 
    LEFT JOIN domain_stats ON (websites.website_id = domain_stats.dstats_domid) 
    WHERE website_id IN (SELECT website_id FROM websites WHERE website_userid = $this_userid) 
    GROUP BY website_url 

Есть ли способ, которым я могу объединить последние 3 запроса int he first one? Потому что теперь .... если у меня есть 100 элементов в очереди, то это 301 запрос (401, если вы включаете подзапрос), которые занимают некоторое время, чтобы сгенерировать страницу.

+0

Вопрос: есть ли причина для подзапроса в последнем запросе? Не могли бы вы просто написать «WHERE website_userid = $ this_userid»? – 2008-12-03 10:10:25

ответ

0

Вот еще попробовать на превращая его в один гигантский запрос. Не знаю, как быстро он будет, хотя ...

Редактировать:Редактировать: ОК, третья попытка. Это должно быть довольно быстро, если вы установите правильные индексы.

SELECT 
    content.con_catid, 
    content.con_posttime, 
    content.con_url, 
    content.con_id, 
    content.con_title, 
    categories.name, 
    users.username, 
    users.user_id, 
    stats1.website_url, 
    websites.website_id, 
    websites.website_shady, 
    websites.website_in_ballast, 
    websites.website_out_ballast, 
    (SELECT COALESCE(sum(dstats_hits),0)+website.website_in_ballast FROM domain_stats WHERE websites.website_id = domain_stats.dstats_domid) as total_in, 
    (SELECT COALESCE(sum(dstats_hits_out),0)+website_out_ballast FROM domain_stats WHERE websites.website_id = domain_stats.dstats_domid) as total_out, 
    (SELECT sum(dstats_hits_out_paid) FROM domain_stats WHERE websites.website_id = domain_stats.dstats_domid) as total_paid, 
    (SELECT count(c2.con_id) FROM content c2 WHERE c2.con_poster = user.user_id AND con_status = 0) as pending, 
    (SELECT count(c2.con_id) FROM content c2 WHERE c2.con_poster = user.user_id AND con_status = 2) as approved 
FROM 
    content 
    LEFT JOIN categories ON (content.con_catid = categories.id) 
    LEFT JOIN users ON (content.con_poster = users.user_id) 
    LEFT JOIN websites ON (website_userid=users.user_id) 
WHERE 
    con_status = 0 
ORDER BY 
    con_posttime 
0

Я не обернуты свой ум вокруг третьего дополнительного запроса еще, но для первых двух, вы можете быть в состоянии сделать что-то вроде:

SELECT count(con_id) as pending, con_poster FROM content 
WHERE con_status = 0 
GROUP BY con_poster 

, а затем присоединиться к ним против первого запроса на con_poster ,

0

Эта функция мне пригодится, может быть, это тоже поможет. Вы можете использовать запрос как один из ваших вариантов.

SELECT 
    col_1, 
    col_2, 
    col_3, 
    (
     SELECT col_1 
     FROM table_2 
     WHERE table_2.col_2 = table_1.col_1 
    ) as 'col4', 
    col_5 
FROM 
    table_1 

Совершенно законный.

0

Хмм ... первый запрос просто выбирает элементы контента, в то время как другие запросы выбирают некоторые статистические данные о них. В первом запросе не используются какие-либо агрегированные функции, а все остальные. Таким образом, единственный способ, с помощью которого я могу присоединиться к ним, - использовать подзапросы. Это не сделает план выполнения намного лучше, но он спасет вас от нескольких сотен поисковых запросов и генерации наборов результатов, поэтому он должен быть несколько быстрее.

Один совет, хотя - две средние запросы могут быть соединены друг с другом, как это:

SELECT 
    count(case when con_status=0 then 1 else null end) as pending, 
    count(case when con_status=2 then 1 else null end) as approved 
FROM 
    content 
WHERE 
    con_poster = '$this_userid' 
0

Соединение по содержанию еще раз для конкретного user_id даст вам возможность рассчитывать, а также.

 
SELECT 
     content.con_catid, 
     content.con_posttime, 
     content.con_url, 
     content.con_id, 
     content.con_title, 
     categories.name, 
     users.username, 
     users.user_id, 
     IFNULL(SUM(CASE WHEN c2.con_status = 0 THEN 1 ELSE 0 END), 0) as pending, 
     IFNULL(SUM(CASE WHEN c2.con_status = 2 THEN 1 ELSE 0 END), 0) as approved 
    FROM content 
    LEFT JOIN categories 
     ON (content.con_catid = categories.id) 
    LEFT JOIN users 
     ON (content.con_poster = users.user_id) 
    LEFT JOIN content as c2 ON users.user_id = c2.con_poster 

    WHERE con_status = 0 

    GROUP BY content.con_id 
    ORDER BY con_posttime 

Не проверено. Возможно, вы сможете дважды присоединиться к контенту и использовать COUNT (DISTINCT c2.con_id) AS для ожидания и COUNT (DISTINCT c3.con_id) AS, одобренный, если оператор CASE замедляется, то вы добавляете c2.con_status = 0 в ваше соединение (для ожидающих сообщений).

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

Для последнего запроса я бы выбрал всю информацию для всех пользователей, которые вы обрабатываете (сохранение всех идентификаторов, а затем их вызов). используя user_id IN() вместо, или подзапрос (в зависимости от того, как вы сделаете свой выбор).

Затем сортировки и обработки данных в коде вместо этого. Это сводит к минимуму количество запросов.

Смежные вопросы