Примерно раз в месяц от провайдера приходят жалобы на запрос:
-------
SELECT t.word AS realword, i.word FROM search_total t LEFT JOIN search_index
i ON t.word = i.word WHERE i.word IS NULL;
-------
Время исполнения, секунд - 12
Кол-во просмотренных строк - 60048
Если вы хотите продолжать пользоваться услугами в текущем
режиме, просим вас максимально оперативно подтвердить решение
о смене тарифного плана на план, предусматривающий эксклюзивную
работу вашей БД.
А так то тарифный план устраивает пока.
Делаю оптимизацию таблиц и пишу им, мол вроде разобрались и т.п.
И вот уже третий раз...
Может кто сталкивался с проблемой?
Комментарии
А вы откройте phpmyadmin, выберите нужную базу и выполните этот запрос.
А лучше используйте ANALIZE, чтобы понять как именно исполняется запрос. Возможно он обрабатывает очень много данных (типа вечный цикл)...
запрос странный... из 2 таблиц по связанным полям у одной из таблиц оно = NULL
всего 60 000 просмотренных записей, у меня в одной таблице >1 000 000 и ни кто не ругается. подозреваю, что мастерхост
А у вас скрипты какие нибудь в планировшике есть?
Вообще надо смотреть SHOW CREATE TABLE для каждой таблицы и делать EXPLAIN SELECT ... для каждого такого запроса. У меня стоит 5.5 друпал, пока что экспериментирую... Вы уверены, что этот запрос ВООБЩЕ нужен?
У меня таблицы создаются так:
CREATE TABLE `search_index` (
`word` varchar(50) NOT NULL default '',
CREATE TABLE `search_total` (
`word` varchar(50) NOT NULL default '',
Соответственно условие не может быть выполнено:
WHERE i.word IS NULL;
Я бы сказал - поэкспериментировать с phpmyadmin - посмотреть, что этот запрос вообще выдает. Далее - попробовать модифицировать код - например WHERE вместо JOIN, либо использование временных таблиц.
Если запрос всегда пустой (как у меня) - может вообще от него избавиться?
удачи
Спасибо, что откликнулись.
Изучал дальше вопрос:
Запрос вызывает стандартный модуль search.module (Drupal 5.2) Текст функции приведен ниже. Смысл запроса в том, что он сравнивает таблицы search_index(40599 строк) и search_total(19449 строк) по полю word, и дальше функция удаляет из таблицы search_total строки по которым нет совпадений в таблице search_index.
Вот функция из search.module вызывающая запрос:
function search_update_totals() {
// Update word IDF (Inverse Document Frequency) counts for new/changed words
foreach (search_dirty() as $word => $dummy) {
// Get total count
$total = db_result(db_query("SELECT SUM(score) FROM {search_index} WHERE word = '%s'", $word));
// Apply Zipf's law to equalize the probability distribution
$total = log10(1 + 1/(max(1, $total)));
db_query("UPDATE {search_total} SET count = %f WHERE word = '%s'", $total, $word);
if (!db_affected_rows()) {
db_query("INSERT INTO {search_total} (word, count) VALUES ('%s', %f)", $word, $total);
}
}
// Find words that were deleted from search_index, but are still in
// search_total. We use a LEFT JOIN between the two tables and keep only the
// rows which fail to join.
$result = db_query("SELECT t.word AS realword, i.word FROM {search_total} t LEFT JOIN {search_index} i ON t.word = i.word WHERE i.word IS NULL");
while ($word = db_fetch_object($result)) {
db_query("DELETE FROM {search_total} WHERE word = '%s'", $word->realword);
}
}
Вроде запрос полезный и ничего в нем страшного быть не должно.
Как считаете его можно оптимизировать?
Вот что выдает EXPLAIN SELECT:
Для для наглядности сделал макет запроса в Access:
Все, понял уже :-(, что LEFT JOIN. Тогда весьма вероятно, что лучше и не получится
Можно попробовать SELECT * FROM (SELECT t.word AS realword, i.word FROM search_total t LEFT JOIN search_index i ON t.word = i.word) tt WHERE word IS NULL;
Но по логике оригинальный запрос будет быстрее...