Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Как при поиске подмножества использовать индекс / 4 сообщений из 4, страница 1 из 1
12.12.2008, 17:38
    #35711763
Gold_
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как при поиске подмножества использовать индекс
В таблице есть поле типа bit varying необходимо найти все записи, которые являются подмножестов заданного множества .
Сооотвествие пожмножеству проверяю следующей процедурой:
Код: plaintext
1.
2.
3.
4.
CREATE OR REPLACE FUNCTION is_subset(bit varying, bit varying)
  RETURNS boolean AS
$BODY$SELECT $ 1 ::label_big | $ 2 ::label_big # $ 2 ::label_big = '0'::label_big;$BODY$
  LANGUAGE 'sql' IMMUTABLE STRICT;
При запросах индексы не используются.
Кто подскажет какой хитрый способ, чтобы задействовать индексы при поиска вхождения в множество.
В качестве примера такой скрипт:
Код: 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.
CREATE DOMAIN label_big
  AS bit( 500 );

CREATE TABLE tdlm_label
(
  label bit varying
);


INSERT INTO tdlm_label
(SELECT '1'::label_big >>  (random()* 30 )::INT  |
	'1'::label_big >>  (random()* 30 )::INT  |
	'1'::label_big >>  (random()* 30 )::INT  |
	'1'::label_big >>  (random()* 30 )::INT  |
	'1'::label_big >>  (random()* 30 )::INT  |
	'1'::label_big >>  (random()* 30 )::INT  |
	'1'::label_big >>  (random()* 30 )::INT  |
	'1'::label_big >>  (random()* 30 )::INT  |
	'1'::label_big >>  (random()* 30 )::INT  |
	'1'::label_big >>  (random()* 30 )::INT  |
	'1'::label_big >>  (random()* 30 )::INT  
 FROM generate_series( 1 , 1000000 )  as s );

SELECT * FROM tdlm_label WHERE is_subset(label,'111111111111111111111111111111111111111111111111111111111111111111111111111111111'::label_big) 

Спасибо.
...
Рейтинг: 0 / 0
14.12.2008, 15:18
    #35713185
Funny_Falcon
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как при поиске подмножества использовать индекс
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
-- Установить contrib/intarray
create index gix_tdlm_label on tdlm_label 
using gist ( ( label_big_to_array(label) ) gist__int_ops );

SELECT * FROM tdlm_label 
WHERE
	label_big_to_array('111111111111111111111111111111111111111111111111111111111111111111111111111111111'::label_big)
	@> label_big_to_array(label);

CREATE OR REPLACE FUNCTION is_subset(label_big, label_big)
  RETURNS boolean AS
$BODY$SELECT label_big_to_array($ 1 ) <@ label_big_to_array($ 2 ) $BODY$
  LANGUAGE 'sql' IMMUTABLE STRICT;

SELECT * FROM tdlm_label 
WHERE
	is_subset(label, '111111111111111111111111111111111111111111111111111111111111111111111111111111111'::label_big);

Примечание: первоначально попробовал gin индекс - получилось намного медленнее, чем gist.
Полагаю, для запроса типа && - т.е. пересечения, а не подмножества, их скорость должна быть равна, или даже у gin скорость будет больше. Но именно для подмножества gist быстрее во много раз.
...
Рейтинг: 0 / 0
14.12.2008, 15:28
    #35713191
Funny_Falcon
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как при поиске подмножества использовать индекс
Простите, функцию забыл:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
create or replace function label_big_to_array(label_big )
returns int4[]
as $$
  select ARRAY( 
	select i 
	from generate_series( 0 , bit_length($ 1 )- 1 ) as i
	where $ 1  << i & '1'::label_big <> '0'::label_big )
$$ language sql immutable strict;
...
Рейтинг: 0 / 0
15.12.2008, 11:47
    #35714168
Gold_
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как при поиске подмножества использовать индекс
Funny_Falcon
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
-- Установить contrib/intarray
create index gix_tdlm_label on tdlm_label 
using gist ( ( label_big_to_array(label) ) gist__int_ops );

SELECT * FROM tdlm_label 
WHERE
	label_big_to_array('111111111111111111111111111111111111111111111111111111111111111111111111111111111'::label_big)
	@> label_big_to_array(label);

CREATE OR REPLACE FUNCTION is_subset(label_big, label_big)
  RETURNS boolean AS
$BODY$SELECT label_big_to_array($ 1 ) <@ label_big_to_array($ 2 ) $BODY$
  LANGUAGE 'sql' IMMUTABLE STRICT;

SELECT * FROM tdlm_label 
WHERE
	is_subset(label, '111111111111111111111111111111111111111111111111111111111111111111111111111111111'::label_big);

Примечание: первоначально попробовал gin индекс - получилось намного медленнее, чем gist.
Полагаю, для запроса типа && - т.е. пересечения, а не подмножества, их скорость должна быть равна, или даже у gin скорость будет больше. Но именно для подмножества gist быстрее во много раз.


Спасибо.
Буду пробовать.
...
Рейтинг: 0 / 0
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Как при поиске подмножества использовать индекс / 4 сообщений из 4, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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