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

И подмечены ли какие-то траблы при индексе на выражение для числового поля ~(f1,(-f2))? (т.е. допетривает ли оптимизатор до юзания таких вещей при банальной сортировке по f1, f2 DESC)?
...
Рейтинг: 0 / 0
CREATE INDEX (f1, f2 DESC) - как?
    #33633135
Funny_Falcon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Для 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
CREATE INDEX (f1, f2 DESC) - как?
    #33633308
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Funny_Falcon грустно что надо изгибхитряцца и при этом еще и Funny_Falcon"теоретически"

да, а такая новая фича как bitmap, при наличии индексов (f1 ASC) и (f2 ASC )сможет их по мере необходимости поюзать через свою хитрую кухню как (f1 ASC,f2 DESC)?
(а то вжеж я тут полный профан - как оно, эта фича т.е., работаит, и фсё такое)
...
Рейтинг: 0 / 0
CREATE INDEX (f1, f2 DESC) - как?
    #33634374
Funny_Falcon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
"теоретически" - значит, что в ситуации, когда для оптимизатора равнозначно:
- 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
CREATE INDEX (f1, f2 DESC) - как?
    #33634382
Funny_Falcon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А bitmap работает только для условий - для order by даже теоретически bitmap не приделаешь (просто если порасуждать) (покрайней мере я не могу себе это представить эффективно)
...
Рейтинг: 0 / 0
CREATE INDEX (f1, f2 DESC) - как?
    #33634417
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вот и интересно в т.ч. для условий
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
CREATE INDEX (f1, f2 DESC) - как?
    #33636096
Funny_Falcon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну и проверь :-) Буду благодарен, если сообщищь результат.
Код: 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
CREATE INDEX (f1, f2 DESC) - как?
    #33636880
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
CREATE INDEX (f1, f2 DESC) - как?
    #33636888
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PS как видим, у разработчиков Постгреса весьма смутные понятия об отношениях порядка и возможности их инверсии. гнустно.
...
Рейтинг: 0 / 0
CREATE INDEX (f1, f2 DESC) - как?
    #33636923
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)
...
Рейтинг: 0 / 0
CREATE INDEX (f1, f2 DESC) - как?
    #33636932
Funny_Falcon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 4321
Не explain, а explain analyze увидеть зотелось бы, ибо разница бывает.
...
Рейтинг: 0 / 0
CREATE INDEX (f1, f2 DESC) - как?
    #33636937
Funny_Falcon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не обращай внимания, я гоню
...
Рейтинг: 0 / 0
CREATE INDEX (f1, f2 DESC) - как?
    #33636984
Funny_Falcon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Странно, а у меня с лимитом сразу пошел индекс:
Код: 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
CREATE INDEX (f1, f2 DESC) - как?
    #33637044
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
CREATE INDEX (f1, f2 DESC) - как?
    #33637055
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Funny_FalconСтранно, а у меня с лимитом сразу пошел индекс:
так у меня ж индекс лругой - см. выше.
...
Рейтинг: 0 / 0
CREATE INDEX (f1, f2 DESC) - как?
    #33637258
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мне кажется, что реализовать возможность создания индексов по некоторым полям 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
CREATE INDEX (f1, f2 DESC) - как?
    #33637431
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
CREATE INDEX (f1, f2 DESC) - как?
    #33637771
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
4321но не совсем понятно, зачем Filter: (в обоих) и Recheck Cond: если выборка шла по индексам?Recheck Cond, как я понимаю, нужен для Bitmap Index Scan, так как скан возвращает страницы, на каждой из которых находится несколько строк, то надо перепроверить каждую строку.

А замена на (j is null)=true не избавит от фильтра?
...
Рейтинг: 0 / 0
CREATE INDEX (f1, f2 DESC) - как?
    #33637896
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
19 сообщений из 19, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / CREATE INDEX (f1, f2 DESC) - как?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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