Оптимизиция запроса
От: WolfHound  
Дата: 12.08.03 05:47
Оценка:
Есть обект у него есть UID унакальный идентификатор в пределах базы.
В некий момент времени изменилось несколько полей что необходимо отразить в базе.
Создается точка изменения (хранится UID, point_id, time). Далие в таблицу значений сохраняютсяизменившиеся поля(у каждого есть PID унакальный идентификатор в пределах объекта).
Вобщем при работе программы получается такая штука строки — точки, столбци pid'ы. Желтые ячейки пустые.

Задача такая:
Есть point и несколько pid'ов(от 5 до 100) Надо выбрать из базы самые последние значения которые были записаны до и в заданной точки.
Сейчас делаю так
select *
from
(
    select point, pid, [value]
    from ValInt
    where (point in (select point from points where uid=46 and point<=100000))
)a
where
(
    point in
    (
        select max(point)
        from
        (
            select    point, pid
            from ValInt
            where (point in (select point from points where uid=46 and point<=100000))
        )b
        where    b.pid = a.pid
    )
)
and (pid in (20,145,555,9834,876235))

Но это медленно. И что самое противное время растет с увеличением размера базы.
А когда много pid'ов план запроса превращается в страшного мутанта
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re: Оптимизиция запроса
От: _MarlboroMan_ Россия  
Дата: 12.08.03 06:03
Оценка:
Здравствуйте, WolfHound, Вы писали:

п.1. разверни "where (point in (select point from points where uid=46 and point<=100000))", тока не забуди индекс создать.
п.2. если таблицы большие, то имеет смысл вынести подзапрос
п.3. повыдергать максимумы от point для каждого pid тоже лучче в отдельном поздапросе и ровно один раз.

получится что-то типа:


-- п.1 + п.2
select v.point, v.pid, v.[value]
into #tmp
from ValInt v
inner join points p on v.point = p.point  and uid=46 and p.point <= 100000

-- п.1 + п.3
select *
from #tmp a
inner join 
(
        select max(point) as point, pid
        from #tmp
        group by pid
) b on a.pid = b.pid and a.point = b.point
where a.pid in (20,145,555,9834,876235)
... << RSDN@Home 1.1 beta 1 >>

— сколько программистов надо чтобы заменить сгоревшую лампочку?
— сколько не бери, а лампочку не поменять — проблема аппаратная, программным путем не решается...
Re[2]: Оптимизиция запроса
От: _MarlboroMan_ Россия  
Дата: 12.08.03 06:11
Оценка:
Здравствуйте, _MarlboroMan_, Вы писали:

чуть не забыл.
если в #tmp попадает МНОГО записей — тоже имеет смысл создать для нее индекс. я бы порекомендовал создать его в любом случае

вот такой например:
create index IX_#tmp_point_pid on #tmp (pid, point)
... << RSDN@Home 1.1 beta 1 >>

— сколько программистов надо чтобы заменить сгоревшую лампочку?
— сколько не бери, а лампочку не поменять — проблема аппаратная, программным путем не решается...
Re[3]: Оптимизиция запроса
От: WolfHound  
Дата: 12.08.03 08:27
Оценка:
Здравствуйте, _MarlboroMan_, Вы писали:

Переделал так

select *
from
(
    select *
    from ValInt
    where (pid in (20,145,555,9834,876235))
)a
where
(
    point in
    (
        select max(point)
        from
        (
            select *
            from ValInt
            where (point in (select point from points where uid=46 and point<=100000))
        )b
        where    b.pid = a.pid
    )
)

Но толку мало.
Уменя есть пара идей как реорганизовать базу. Попробую напишу.

ЗЫ Твой вариант даже с индексом оказался хуже чем первоночальный запрос. Вывод:Не парьте мозги оптимизатору.
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[4]: Оптимизиция запроса
От: _MarlboroMan_ Россия  
Дата: 12.08.03 08:34
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>ЗЫ Твой вариант даже с индексом оказался хуже чем первоночальный запрос. Вывод:Не парьте мозги оптимизатору.


добрый ты...

PS а насчет запроса: скорее уж твой парит оптимизатора, а не мой
... << RSDN@Home 1.1 beta 1 >>

— сколько программистов надо чтобы заменить сгоревшую лампочку?
— сколько не бери, а лампочку не поменять — проблема аппаратная, программным путем не решается...
Re[5]: Оптимизиция запроса
От: WolfHound  
Дата: 12.08.03 08:47
Оценка:
Здравствуйте, _MarlboroMan_, Вы писали:

_MM_>добрый ты...

Ну какой есть
_MM_>PS а насчет запроса: скорее уж твой парит оптимизатора, а не мой
Парит может он и сильнее но простора для оптимизации ИМХО дает больше.
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re: Оптимизиция запроса
От: KisA Россия  
Дата: 12.08.03 11:02
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Есть обект у него есть UID унакальный идентификатор в пределах базы.

WH>В некий момент времени изменилось несколько полей что необходимо отразить в базе.
WH>Создается точка изменения (хранится UID, point_id, time). Далие в таблицу значений сохраняютсяизменившиеся поля(у каждого есть PID унакальный идентификатор в пределах объекта).
WH>Вобщем при работе программы получается такая штука строки — точки, столбци pid'ы. Желтые ячейки пустые.
WH>
WH>Задача такая:
WH>Есть point и несколько pid'ов(от 5 до 100) Надо выбрать из базы самые последние значения которые были записаны до и в заданной точки.
WH>Сейчас делаю так
WH>
WH>select *
WH>from
WH>(
WH>    select point, pid, [value]
WH>    from ValInt
WH>    where (point in (select point from points where uid=46 and point<=100000))
WH>)a
WH>where
WH>(
WH>    point in
WH>    (
WH>        select max(point)
WH>        from
WH>        (
WH>            select    point, pid
WH>            from ValInt
WH>            where (point in (select point from points where uid=46 and point<=100000))
WH>        )b
WH>        where    b.pid = a.pid
WH>    )
WH>)
WH>and (pid in (20,145,555,9834,876235))
WH>

WH>Но это медленно. И что самое противное время растет с увеличением размера базы.
WH>А когда много pid'ов план запроса превращается в страшного мутанта

А так попробовать:
select point, pid, [value]
from ValInt
where ( pid, point )
in
( select ValInt.pid, max( ValInt.point)
from ValInt join points on ValInt.point = points.point and points.uid = 46
where ValInt.point < 100000
and ValInt.pid in (20,145,555,9834,876235)
group by ValInt.pid
)
Re[2]: Оптимизиция запроса
От: WolfHound  
Дата: 12.08.03 11:32
Оценка:
Здравствуйте, KisA, Вы писали:


select point, pid, [value]
from ValInt
where ( pid, point )
in
( 
    select ValInt.pid, max( ValInt.point)
    from ValInt join points on ValInt.point = points.point and points.uid = 46 
    where ValInt.point < 100000
    and ValInt.pid in (20,145,555,9834,876235)
    group by ValInt.pid 
)



Line 3: Incorrect syntax near ','.

Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[3]: Оптимизиция запроса
От: KisA Россия  
Дата: 12.08.03 11:41
Оценка:
WH>
WH>Line 3: Incorrect syntax near ','.
WH>

WH>

Жаль, а Oracle берет.
Re: Оптимизиция запроса
От: Аноним  
Дата: 12.08.03 12:52
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>
WH>select *
WH>from
WH>(
WH>    select point, pid, [value]
WH>    from ValInt
WH>    where (point in (select point from points where uid=46 and point<=100000))
WH>)a
WH>where
WH>(
WH>    point in
WH>    (
WH>        select max(point)
WH>        from
WH>        (
WH>            select    point, pid
WH>            from ValInt
WH>            where (point in (select point from points where uid=46 and point<=100000))
WH>        )b
WH>        where    b.pid = a.pid
WH>    )
WH>)
WH>and (pid in (20,145,555,9834,876235))
WH>

WH>Но это медленно. И что самое противное время растет с увеличением размера базы.
WH>А когда много pid'ов план запроса превращается в страшного мутанта
Не совсем понял, что нужно получить, но судя по запросу догадываюсь что нужен group by.
Примерно так:
select ValInt.*
from
ValInt inner join
(
    select max(point) as point, pid
    from ValInt inner join points on ValInt.point=points.point
         where points.uid=46 and points.point<=100000 and ValInt.pid in (20,145,555,9834,876235)
         group by pid
) a on ValInt.point=a.point and ValInt.pid=a.pid
Re[2]: Это было от меня, а не от Анонима :)
От: AlexanderPo  
Дата: 12.08.03 13:00
Оценка:
-
Re[3]: Это было от меня, а не от Анонима :)
От: WolfHound  
Дата: 13.08.03 04:32
Оценка:
Здравствуйте, AlexanderPo, Вы писали:

В 57-58 раз медленней чем мой модифицированый Не смотря на то что у твоего план запроса выглядит лучше
        select *
        from
        (
            select *
            from ValInt
            where (pid in (20,145,555,9834,876235))
        )a
        where
        (
            point in
            (
                select max(point)
                from
                (
                    select *
                    from ValInt
                    where (point in (select point from points where uid=46 and point<=100000))
                )b
                where    b.pid = a.pid
            )
        )


ЗЫ Добрый я всетки
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.