[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Перегруз базы данных
Arcky
Доброго времени суток!
Появилась следующая проблема, хостер жалуется:



Код
Время исполнения, секунд   - 15
Кол-во просмотренных строк - 189104
Запрос:
-------
use 1gb_supertest4;
SELECT P.*, max(Prev.id_pic) as prev, min(Next.id_pic) as next FROM
pictures P
                LEFT JOIN pictures Prev on (Prev.category_ind=P.category_ind
and Prev.id_pic<P.id_pic)
                LEFT JOIN pictures Next on (Next.category_ind=P.category_ind
and Next.id_pic>P.id_pic)
                WHERE P.id_pic='4154' GROUP BY P.category_ind;


Причем: в таблице pictures всего 3500 записей, в таблице category не больше 30-40.
В чем проблема? Я просто механизма этого не совсем понимаю, как зпрос оптимизировать?

Если что, он просто выбирает картинку по ID и идентификаторы следующей и предыдущей картинки в этой категории.
Заранее благодарю за ответ.




Спустя 2 часа, 24 минуты, 56 секунд (25.09.2008 - 18:32) vasa_c написал(а):
структуру таблиц покажите

Спустя 2 дня, 18 часов, 32 минуты, 53 секунды (28.09.2008 - 13:05) Arcky написал(а):
Вот так пойдет?
Код
CREATE TABLE `categories` (
  `category_ind` int(11) NOT NULL auto_increment,
  `category_name` varchar(30) NOT NULL default '',
  `category_title` varchar(30) NOT NULL default '',
  `category_desc` text NOT NULL,
  `num` int(16) default '0',
  `loads` int(16) default '0',
  PRIMARY KEY  (`category_ind`)
)

Код
CREATE TABLE `pictures` (
  `id_pic` int(11) NOT NULL auto_increment,
  `category_ind` int(11) NOT NULL default '0',
  `category_name` varchar(30) NOT NULL default '',
  `file_name` varchar(30) NOT NULL default '',
  `name_pic` varchar(30) NOT NULL default '',
  `description` text NOT NULL,
  `added_by` varchar(30) NOT NULL default '',
  `type` int(11) NOT NULL default '0',
  `loads` int(16) default '0',
  `total_loads` int(11) NOT NULL default '0',
  `time` int(11) NOT NULL default '0',
  PRIMARY KEY  (`id_pic`),
  KEY `category_ind` (`category_ind`),
  KEY `type` (`type`),
  KEY `added_by` (`added_by`)
)

Спустя 9 часов, 26 минут, 57 секунд (28.09.2008 - 22:32) Ghost написал(а):
ну всё правильно..
ты из таблицы выбираешь запись, а вместе с ней ВСЕ предыдущие и последующие записи из этой категории..
сделай в 2 запроса (или через union) и заюзай limit

Спустя 17 часов, 16 минут, 22 секунды (29.09.2008 - 15:48) Arcky написал(а):
А можно пример?!? Очень срочно! У меня уже сайт заблокировали, а там трафик очень большой..........................
Я в панике и не пойму, как это осуществить!

Спустя 2 минуты, 30 секунд (29.09.2008 - 15:51) Arcky написал(а):
И обратите внимание на цифры! В одной таблице 3500 записей, в другой 30. А просматривается 181 ТЫСЯЧА!

Спустя 35 минут, 54 секунды (29.09.2008 - 16:26) Alchemist написал(а):
Советую серьезно почитать про JOIN'ы и порядок работы запроса вообще.

В-кратце что у тебя происходит:
1) функции MAX() и MIN() выполняются только после того как составлена "рабочая таблица" - набор всех строк подходящих под условия.

2) "рабочая таблица" составляется путем соединения (JOIN) указаных тобой таблиц. При этом поскольку указаные условия являются условиями вида "один-к-многим", то таблицы соединяются картезианским (векторным) умножением, т.е. для каждой строки первой таблицы подставляются все подходящие строки из второй.
Так например если у тебя была 1 подходящая строка в первой таблице и 20 во второй, то в итоговой таблице будет 20 строк; если в первой подошло 10 строк, а во второй 15 - будет 150 (по 15 строк на каждую строку из первой таблицы); и т.д.

Теперь посмотрим на твой случай. Предположим мы рассматриваем картинку с id = 51, которая расположена на 51-м месте, т.е. до нее есть 50 картинок и после нее есть 3449 картинок (всего 3500).
У тебя соединяются три таблицы: `P`, `Prev` и `Next`, которые фактически являются одной и той же таблицей.

- в `P` есть только одна подходящая строка (id = 51)
- в `Prev` есть 50 подходящих строк (все те у которых id < 51)
- в `Next` есть 3449 подходящих строк (все те у которых id > 51)

Итого в "рабочей таблице" будет 1 * 50 * 3449 = 172 450 строк. И именно их будут просматривать функции MAX() и MIN() в поисках правильных значений.

Это было к вопросу о кол-ве строк. Совсем другой вопрос - время работы запроса. Оно неимоверно велико для таких таблиц. Если запрос выглядит именно так как ты нам показываешь, то скорее всего что-то не в порядке у самого хостера.

Можешь попробовать запустить запрос
Код
OPTIMIZE TABLE `pictures`
и проверить время работы запроса после этого... Возможно поможет...

Спустя 4 часа, 36 минут, 9 секунд (29.09.2008 - 21:03) Ghost написал(а):
SELECT * FROM pictures WHERE id_pic<=4154 ORDER BY id_pic DESC Limit 2
SELECT * FROM pictures WHERE id_pic>4154 ORDER BY id_pic ASC Limit 1

Спустя 11 часов, 7 минут, 41 секунда (30.09.2008 - 08:10) sergeiss написал(а):
Ghost - и еще union бы написать между этими двумя строками, чтоб получить один запрос, а не два.

Спустя 12 часов, 9 минут, 43 секунды (30.09.2008 - 20:20) Alchemist написал(а):
...который все равно будет работать не правильно, потому что потеряно условие `Prev/Next`.`category_ind` = `P`.`category_ind`

Спустя 40 минут, 51 секунда (30.09.2008 - 21:01) sergeiss написал(а):
Цитата(Alchemist @ 30.9.2008, 21:20) [snapback]49753[/snapback]
...который все равно будет работать не правильно, потому что потеряно условие `Prev/Next`.`category_ind` = `P`.`category_ind`

А это зачем тут?
Ghost правильно написал, эти его 2 запроса должны выдать: первый 2 записи меньше и (если есть) совпадающую с указанным индексом, а второй - одну запись больше указанного индекса. Если их объединить, то получится 3 записи после одного запроса.
А твои условия непонятно зачем.

Спустя 57 минут, 34 секунды (30.09.2008 - 21:58) Ghost написал(а):
а, не, Alchemist прав.. связку по категориям надо, пардон, из головы вылетело smile.gif
а про юнион - попробуй, напиши smile.gif
в даном случае всё укладывать в один запрос неоптимально

SELECT * FROM pictures WHERE id_pic=4154

SELECT * FROM pictures WHERE id_pic<=4154 AND category_ind=... ORDER BY id_pic DESC Limit 1
SELECT * FROM pictures WHERE id_pic>4154 AND category_ind=... ORDER BY id_pic ASC Limit 1


_____________
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.