Появилась следующая проблема, хостер жалуется:
Код
Время исполнения, секунд - 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;
Кол-во просмотренных строк - 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`)
)
`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`)
)
`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
ты из таблицы выбираешь запись, а вместе с ней ВСЕ предыдущие и последующие записи из этой категории..
сделай в 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() в поисках правильных значений.
Это было к вопросу о кол-ве строк. Совсем другой вопрос - время работы запроса. Оно неимоверно велико для таких таблиц. Если запрос выглядит именно так как ты нам показываешь, то скорее всего что-то не в порядке у самого хостера.
Можешь попробовать запустить запрос
В-кратце что у тебя происходит:
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
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 прав.. связку по категориям надо, пардон, из головы вылетело 
а про юнион - попробуй, напиши
в даном случае всё укладывать в один запрос неоптимально
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

а про юнион - попробуй, напиши

в даном случае всё укладывать в один запрос неоптимально
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
_____________