Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / CREATE INDEX (f1, f2 DESC) - как? / 19 сообщений из 19, страница 1 из 1
29.03.2006, 14:10
    #33632352
4321
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
CREATE INDEX (f1, f2 DESC) - как?
правильно ли я понимаю, что такого
Код: plaintext
CREATE INDEX (f1, f2 DESC) 
в постгресе не предусмотрено? (я не нашел) Как сделать для нечислового типа?

И подмечены ли какие-то траблы при индексе на выражение для числового поля ~(f1,(-f2))? (т.е. допетривает ли оптимизатор до юзания таких вещей при банальной сортировке по f1, f2 DESC)?
...
Рейтинг: 0 / 0
29.03.2006, 17:04
    #33633135
Funny_Falcon
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
CREATE INDEX (f1, f2 DESC) - как?
Для int8 пример:
Находим в pg_class operatorclass int8_ops, слегка меняем
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
CREATE OPERATOR CLASS int8_ops_desc
   FOR TYPE int8 USING btree AS
   OPERATOR  5   <,
   OPERATOR  5   <(int8, int2),
   OPERATOR  5   <(int8, int4),
   OPERATOR  4   <=,
   OPERATOR  4   <=(int8, int2),
   OPERATOR  4   <=(int8, int4),
   OPERATOR  3   =,
   OPERATOR  3   =(int8, int2),
   OPERATOR  3   =(int8, int4),
   OPERATOR  2   >=,
   OPERATOR  2   >=(int8, int2),
   OPERATOR  2   >=(int8, int4),
   OPERATOR  1   >,
   OPERATOR  1   >(int8, int2),
   OPERATOR  1   >(int8, int4),
   FUNCTION  1   btint8cmp(int8, int8),
   FUNCTION  1   btint84cmp(int8, int4),
   FUNCTION  1   btint82cmp(int8, int2);
и используем его при создании индекса:

Код: plaintext
1.
create index ij_ix_1 on ij (i,j int8_ops_desc);
и тогда order by i, j desc теоретически может использовать этот индекс
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
--"теоретически" потому что на простой тестовой таблице 
create table ij (i int8, j int8); 
insert into ij
select i,j from generate_series( 1 , 1001 ) i,generate_series( 1 , 1501 ) j
order by random();
create index ij_ix_1 on ij (i,j int8_ops_desc);

--мне пришлось указать:
set enable_seqscan=off;
set enable_bitmapscan=off;
--для запроса
select * from ij
where i> 700  and i <  1000 
 order by i, j desc;
--при этом план:
Index Scan using ij_ix_1 on ij  (cost= 0 . 00 .. 800600 . 02  rows= 446302  width= 16 )
  Index Cond: ((i >  700 ) AND (i <  1000 ))
...
Рейтинг: 0 / 0
29.03.2006, 17:44
    #33633308
4321
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
CREATE INDEX (f1, f2 DESC) - как?
Funny_Falcon грустно что надо изгибхитряцца и при этом еще и Funny_Falcon"теоретически"

да, а такая новая фича как bitmap, при наличии индексов (f1 ASC) и (f2 ASC )сможет их по мере необходимости поюзать через свою хитрую кухню как (f1 ASC,f2 DESC)?
(а то вжеж я тут полный профан - как оно, эта фича т.е., работаит, и фсё такое)
...
Рейтинг: 0 / 0
30.03.2006, 10:47
    #33634374
Funny_Falcon
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
CREATE INDEX (f1, f2 DESC) - как?
"теоретически" - значит, что в ситуации, когда для оптимизатора равнозначно:
- index (i, j) и order by i, j;
- index (i,j int8_ops_desc); и order by i, j desc;
В обоих случаях оптимизатор использовал индекс в данном простом примере только после натягивания за уши. И самое интересное - оптимизатор был прав: считать таблицу (2М записей) и отсортировать действительно получалось у него шустрее чем по индексу сканить. Может если в таблице будет больше мертвых версий (после update/delete) скан по индеку и будет эфективней, надо будет попробовать.
Если запрос выберет обычный индекс для order by f1, if2,то этот же запрос выберет изменённый индекс для order by f1, f2 desc. Но это будет далеко не всегда, ибо оптимизатор cost-based а не rule-based И ЭТО ПРАВИЛЬНО !!!!! ;0)
...
Рейтинг: 0 / 0
30.03.2006, 10:49
    #33634382
Funny_Falcon
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
CREATE INDEX (f1, f2 DESC) - как?
А bitmap работает только для условий - для order by даже теоретически bitmap не приделаешь (просто если порасуждать) (покрайней мере я не могу себе это представить эффективно)
...
Рейтинг: 0 / 0
30.03.2006, 11:01
    #33634417
4321
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
CREATE INDEX (f1, f2 DESC) - как?
вот и интересно в т.ч. для условий
where i>700 and i < 1000
AND j<50
order by i, j desc;
что будет

вообще говоря у меня задача такого вида
Код: plaintext
1.
2.
3.
...
WHERE a.a = NEW.a
	AND a.b = NEW.b
ORDER BY a.actual, a.id DESC LIMIT  1 ;
(версионная таблица) т.е. выбор мульонов мне не нужен.
кажется для нее неплох индекс
(a,b,actual,id DESC)
...
Рейтинг: 0 / 0
30.03.2006, 18:46
    #33636096
Funny_Falcon
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
CREATE INDEX (f1, f2 DESC) - как?
Ну и проверь :-) Буду благодарен, если сообщищь результат.
Код: plaintext
1.
2.
3.
4.
5.
6.
explain select * from ij where i= 1000  order by j desc limit  1 ;

Limit  (cost= 0 . 00 .. 1 . 87  rows= 1  width= 16 )
  ->  Index Scan using ij_ix_1 on ij  (cost= 0 . 00 .. 2983 . 91  rows= 1598  width= 16 )
        Index Cond: (i =  1000 )

Т.е. на моей табличке пашет :-)


А по поводу AND j<50 - только что прочитал в доке - будет скан по индексу с фильтром j<50.
...
Рейтинг: 0 / 0
31.03.2006, 10:31
    #33636880
4321
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
CREATE INDEX (f1, f2 DESC) - как?
Funny_FalconА по поводу AND j<50 - только что прочитал в доке - будет скан по индексу с фильтром j<50.этто я погорячился. Это не эквивалентно лимиту. вот для i=xxx AND j<yyy должен чисто индекс работать.


Вот кстати для твоей таблички (записей токмо изрядно поменьше):
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
CREATE UNIQUE INDEX udx_ij_ix_1
  ON ij
  USING btree
  (i, (- j));

EXPLAIN ANALYZE 
SELECT * FROM ij WHERE i BETWEEN  100  AND  120 
ORDER BY i,j DESC LIMIT  10 ;

"Limit  (cost=2311.30..2311.33 rows=10 width=16) (actual time=405.047..405.097 rows=10 loops=1)"
"  ->  Sort  (cost=2311.30..2334.26 rows=9183 width=16) (actual time=405.041..405.059 rows=10 loops=1)"
"        Sort Key: i, j"
"        ->  Bitmap Heap Scan on ij  (cost=92.10..1706.84 rows=9183 width=16) (actual time=3.700..44.087 rows=10521 loops=1)"
"              Recheck Cond: ((i >= 100) AND (i <= 120))"
"              ->  Bitmap Index Scan on udx_ij_ix_1  (cost=0.00..92.10 rows=9183 width=0) (actual time=3.259..3.259 rows=10521 loops=1)"
"                    Index Cond: ((i >= 100) AND (i <= 120))"
"Total runtime: 436.913 ms"


--а если
EXPLAIN ANALYZE 
SELECT * FROM ij WHERE i BETWEEN  100  AND  120 
ORDER BY i,(-j) LIMIT  10 ;

"Limit  (cost=0.00..15.37 rows=10 width=16) (actual time=0.158..0.364 rows=10 loops=1)"
"  ->  Index Scan using udx_ij_ix_1 on ij  (cost=0.00..14115.20 rows=9183 width=16) (actual time=0.153..0.323 rows=10 loops=1)"
"        Index Cond: ((i >= 100) AND (i <= 120))"
"Total runtime: 0.428 ms"
...
Рейтинг: 0 / 0
31.03.2006, 10:33
    #33636888
4321
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
CREATE INDEX (f1, f2 DESC) - как?
PS как видим, у разработчиков Постгреса весьма смутные понятия об отношениях порядка и возможности их инверсии. гнустно.
...
Рейтинг: 0 / 0
31.03.2006, 10:41
    #33636923
LeXa NalBat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
CREATE INDEX (f1, f2 DESC) - как?
4321PS как видим, у разработчиков Постгреса весьма смутные понятия об отношениях порядка и возможности их инверсии. гнустно. Или все-таки ясные? Вот например:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
=> select * from ( select  1  as id union select  2  as id union select null as id ) as a order by -id;
 id
----
   2 
   1 

( 3  rows)

=> select * from ( select  1  as id union select  2  as id union select null as id ) as a order by id desc;
 id
----

   2 
   1 
( 3  rows)
...
Рейтинг: 0 / 0
31.03.2006, 10:43
    #33636932
Funny_Falcon
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
CREATE INDEX (f1, f2 DESC) - как?
2 4321
Не explain, а explain analyze увидеть зотелось бы, ибо разница бывает.
...
Рейтинг: 0 / 0
31.03.2006, 10:44
    #33636937
Funny_Falcon
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
CREATE INDEX (f1, f2 DESC) - как?
Не обращай внимания, я гоню
...
Рейтинг: 0 / 0
31.03.2006, 10:59
    #33636984
Funny_Falcon
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
CREATE INDEX (f1, f2 DESC) - как?
Странно, а у меня с лимитом сразу пошел индекс:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
explain analize
select * from ij
where i between  100  and  120 
order by i, j desc;

"Limit  (cost=0.00..11.97 rows=10 width=16) (actual time=0.034..0.070 rows=10 loops=1)"
"  ->  Index Scan using ij_ix_1 on ij  (cost=0.00..33853.32 rows=28281 width=16) (actual time=0.030..0.054 rows=10 loops=1)"
"        Index Cond: ((i >= 100) AND (i <= 120))"
"Total runtime: 0.154 ms"
У меня random_page_cost = 2 в конфиге.
...
Рейтинг: 0 / 0
31.03.2006, 11:15
    #33637044
4321
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
CREATE INDEX (f1, f2 DESC) - как?
LeXa NalBat 4321PS как видим, у разработчиков Постгреса весьма смутные понятия об отношениях порядка и возможности их инверсии. гнустно. Или все-таки ясные? Вот например:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
=> select * from ( select  1  as id union select  2  as id union select null as id ) as a order by -id;
 id
----
   2 
   1 

( 3  rows)

=> select * from ( select  1  as id union select  2  as id union select null as id ) as a order by id desc;
 id
----

   2 
   1 
( 3  rows)
кхм. как бы этто помяхше.
даже если считать, что мои наезды относились к данному типу инверсии, то:

1. выколотую точку (оо без знака или тот же нулл) всегда можно оставить выколотой точкой. Вы не находите? (кстати не пойму, почему Нулл - самое больше в постгресе - это чем то норматируецца? А то я привык шо нулл - самое махонькое) Инверитировать же прочее мн-во ничто не мешает без изгибхитрения усера. Кажецца индекс не настолько сложная структура, чтобы из нее низзя было выколоть единственную точку "на лету"? Вот для вас задача обхождения алгоритмом одной точки из упорядоченного мн-ва - действительно сложна ?
2. А если я напишу в поле Not Null - так что, вы продолжите настаивать на ястности понимания инверсии и требования от усера неких извращений?

Я же имел в виду то, что вместо указания в индексе примитивного служебного ASC/DESC г-да разработчики видимо рекоменудют занимацца всякой лабудой методом копи-паста, не имеющей никакого отношения к проэктированию Б.Д.
...
Рейтинг: 0 / 0
31.03.2006, 11:18
    #33637055
4321
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
CREATE INDEX (f1, f2 DESC) - как?
Funny_FalconСтранно, а у меня с лимитом сразу пошел индекс:
так у меня ж индекс лругой - см. выше.
...
Рейтинг: 0 / 0
31.03.2006, 12:13
    #33637258
LeXa NalBat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
CREATE INDEX (f1, f2 DESC) - как?
Мне кажется, что реализовать возможность создания индексов по некоторым полям ASC, по другим - DESC, можно. Но мнения разработчиков постгреса на этот счет я не знаю. :)

43211. выколотую точку (оо без знака или тот же нулл) всегда можно оставить выколотой точкой. Вы не находите? Инверитировать же прочее мн-во ничто не мешает без изгибхитрения усера. Кажецца индекс не настолько сложная структура, чтобы из нее низзя было выколоть единственную точку "на лету"?По-моему да.

Однако в постгресе поиск по IS NULL невозможен по индексу. Возможно, здесь кроется корень проблемы.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
=> create table t1 ( f1 integer );
CREATE TABLE
=> create index i1 on t1 (f1);
CREATE INDEX
=> set enable_seqscan to off;
SET
=> explain select * from t1 where f1= 0 ;
                          QUERY PLAN
---------------------------------------------------------------
 Index Scan using i1 on t1  (cost= 0 . 00 .. 29 . 53  rows= 11  width= 4 )
   Index Cond: (f1 =  0 )
( 2  rows)

=> explain select * from t1 where f1 is null;
                            QUERY PLAN
-------------------------------------------------------------------
 Seq Scan on t1  (cost= 100000000 . 00 .. 100000031 . 40  rows= 11  width= 4 )
   Filter: (f1 IS NULL)
( 2  rows)
...
Рейтинг: 0 / 0
31.03.2006, 12:54
    #33637431
4321
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
CREATE INDEX (f1, f2 DESC) - как?
LeXa NalBatОднако в постгресе поиск по IS NULL невозможен по индексу. Возможно, здесь кроется корень проблемы.
пожалуй это надо запомнить 11.2. Index TypesConstructs equivalent to combinations of these operators, such as BETWEEN and IN, can also be implemented with a B-tree index search. (But note that IS NULL is not equivalent to = and is not indexable.) Мдя. И как токо недоумки из мелкософт и т.п. этого не понимают (и индексируют Null не вдаваясь в глубокоученые соображения) ?

Правда есть и тут отмазка - можно сделать так :
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
/*
insert into ij
select i,Null from generate_series(1,100) i
order by random();
*/
/*

CREATE  INDEX udx_ij_ix_null
  ON ij
  USING btree
  (i,  ( j IS NULL) );
*/
EXPLAIN ANALYZE 
SELECT * FROM ij WHERE i BETWEEN  100  AND  120 
ORDER BY i,j IS NULL LIMIT  10 ;

"Limit  (cost=0.00..15.34 rows=10 width=16) (actual time=0.144..0.401 rows=10 loops=1)"
"  ->  Index Scan using udx_ij_ix_null on ij  (cost=0.00..14087.24 rows=9183 width=16) (actual time=0.139..0.356 rows=10 loops=1)"
"        Index Cond: ((i >= 100) AND (i <= 120))"
"Total runtime: 0.479 ms"

или
EXPLAIN ANALYZE 
SELECT * FROM ij WHERE i =  100  AND 
j IS NULL
ORDER BY i,j  LIMIT  10 ;

"Limit  (cost=647.79..647.79 rows=1 width=16) (actual time=0.088..0.094 rows=1 loops=1)"
"  ->  Sort  (cost=647.79..647.79 rows=1 width=16) (actual time=0.083..0.086 rows=1 loops=1)"
"        Sort Key: i, j"
"        ->  Bitmap Heap Scan on ij  (cost=3.48..647.78 rows=1 width=16) (actual time=0.029..0.032 rows=1 loops=1)"
"              Recheck Cond: (i = 100)"
"              Filter: (j IS NULL)"
"              ->  Bitmap Index Scan on udx_ij_ix_null  (cost=0.00..3.48 rows=246 width=0) (actual time=0.017..0.017 rows=1 loops=1)"
"                    Index Cond: ((i = 100) AND ((j IS NULL) = true))"
"Total runtime: 0.150 ms"

-- и для сложных запросов
EXPLAIN ANALYZE 
SELECT * FROM ij WHERE i = 100 
AND 
(j IS NULL OR j> 700 )
ORDER BY i,j  LIMIT  10 ;


"        Sort Key: i, j"
"        ->  Bitmap Heap Scan on ij  (cost=10.46..14.47 rows=1 width=16) (actual time=0.310..0.312 rows=1 loops=1)"
"              Recheck Cond: ((i = 100) AND (((i = 100) AND (j IS NULL)) OR ((i = 100) AND (j > 700))))"
"              Filter: ((j IS NULL) OR (j > 700))"
"              ->  BitmapAnd  (cost=10.46..10.46 rows=1 width=0) (actual time=0.299..0.299 rows=0 loops=1)"
"                    ->  Bitmap Index Scan on udx_ij_ix_null  (cost=0.00..4.72 rows=492 width=0) (actual time=0.196..0.196 rows=502 loops=1)"
"                          Index Cond: (i = 100)"
"                    ->  BitmapOr  (cost=5.48..5.48 rows=246 width=0) (actual time=0.029..0.029 rows=0 loops=1)"
"                          ->  Bitmap Index Scan on udx_ij_ix_null  (cost=0.00..3.48 rows=246 width=0) (actual time=0.011..0.011 rows=1 loops=1)"
"                                Index Cond: ((i = 100) AND ((j IS NULL) = true))"
"                          ->  Bitmap Index Scan on udx_ij_ix_2  (cost=0.00..2.01 rows=1 width=0) (actual time=0.012..0.012 rows=0 loops=1)"
"                                Index Cond: ((i = 100) AND (j > 700))"
"Total runtime: 0.393 ms"
но не совсем понятно, зачем Filter: (в обоих) и Recheck Cond: если выборка шла по индексам?
...
Рейтинг: 0 / 0
31.03.2006, 14:34
    #33637771
LeXa NalBat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
CREATE INDEX (f1, f2 DESC) - как?
4321но не совсем понятно, зачем Filter: (в обоих) и Recheck Cond: если выборка шла по индексам?Recheck Cond, как я понимаю, нужен для Bitmap Index Scan, так как скан возвращает страницы, на каждой из которых находится несколько строк, то надо перепроверить каждую строку.

А замена на (j is null)=true не избавит от фильтра?
...
Рейтинг: 0 / 0
31.03.2006, 15:15
    #33637896
4321
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
CREATE INDEX (f1, f2 DESC) - как?
LeXa NalBatА замена на (j is null)=true не избавит от фильтра?Где замена?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
CREATE INDEX udx_ij_ix_null1
  ON ij
  USING btree
  (i, ((j IS NULL) = TRUE));

--1
set enable_bitmapscan=on;

EXPLAIN ANALYZE 
SELECT * FROM ij WHERE i =  100  AND 
(j IS NULL) = true
ORDER BY i,j  LIMIT  100 ;
"Limit  (cost=647.79..647.79 rows=1 width=16) (actual time=0.051..0.059 rows=1 loops=1)"
"  ->  Sort  (cost=647.79..647.79 rows=1 width=16) (actual time=0.046..0.048 rows=1 loops=1)"
"        Sort Key: i, j"
"        ->  Bitmap Heap Scan on ij  (cost=3.48..647.78 rows=1 width=16) (actual time=0.030..0.032 rows=1 loops=1)"
"              Recheck Cond: (i = 100)"
"              Filter: (j IS NULL)"
"              ->  Bitmap Index Scan on udx_ij_ix_null1  (cost=0.00..3.48 rows=246 width=0) (actual time=0.022..0.022 rows=1 loops=1)"
"                    Index Cond: ((i = 100) AND ((j IS NULL) = true))"
"Total runtime: 0.108 ms"

--2
set enable_bitmapscan=off;

EXPLAIN ANALYZE 
SELECT * FROM ij WHERE i =  100  AND 
(j IS NULL) = true
ORDER BY i,j  LIMIT  100 ;

"Limit  (cost=913.59..913.60 rows=1 width=16) (actual time=0.044..0.052 rows=1 loops=1)"
"  ->  Sort  (cost=913.59..913.60 rows=1 width=16) (actual time=0.039..0.041 rows=1 loops=1)"
"        Sort Key: i, j"
"        ->  Index Scan using udx_ij_ix_null1 on ij  (cost=0.00..913.58 rows=1 width=16) (actual time=0.022..0.025 rows=1 loops=1)"
"              Index Cond: ((i = 100) AND ((j IS NULL) = true))"
"              Filter: (j IS NULL)"
"Total runtime: 0.095 ms"
...
Рейтинг: 0 / 0
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / CREATE INDEX (f1, f2 DESC) - как? / 19 сообщений из 19, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]