powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / LIMIT не использует индекс
6 сообщений из 6, страница 1 из 1
LIMIT не использует индекс
    #34975444
_Андрей_М
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Интересный глюк:
Есть таблица с составным индексом
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
CREATE TABLE vizits
(
  fname character varying( 20 ),
  nrec integer,
  . . .
)
WITH (OIDS=TRUE);
ALTER TABLE vizits OWNER TO sysdba;

  . . .

-- Index: vizits_fname_nrec

-- DROP INDEX vizits_fname_nrec;

CREATE INDEX vizits_fname_nrec
  ON vizits
  USING btree
  (fname, nrec);

  . . .
Делаю запрос с условием по одному из полей:
Код: plaintext
select * from vizits where fname = 'SOL071119'
План:
Код: plaintext
1.
2.
3.
4.
Bitmap Heap Scan on vizits  (cost= 41711 . 06 .. 648476 . 00  rows= 594815  width= 313 )
  Recheck Cond: ((fname)::text = 'SOL071119'::text)
  ->  Bitmap Index Scan on vizits_fname_nrec  (cost= 0 . 00 .. 41562 . 35  rows= 594815  width= 0 )
        Index Cond: ((fname)::text = 'SOL071119'::text)
Добавляю ограничение:
Код: plaintext
select * from vizits where fname = 'SOL071119' limit  100 ;
План:
Код: plaintext
1.
2.
3.
Limit  (cost= 0 . 00 .. 113 . 91  rows= 100  width= 313 )
  ->  Seq Scan on vizits  (cost= 0 . 00 .. 677567 . 97  rows= 594815  width= 313 )
        Filter: ((fname)::text = 'SOL071119'::text)
Вопрос:
А чё так? Ограничение по количеству выводимых строк делает необязательным поиск по индексу?
PostgreSQL 8.2.5 on i686-pc-mingw32, compiled by GCC gcc.exe (GCC) 3.4.2 (mingw-special) на WinXP Home
...
Рейтинг: 0 / 0
LIMIT не использует индекс
    #34975655
Andrey Daeron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Андрей_МИнтересный глюк:

Глюк по немецки - счастье.

_Андрей_М
Добавляю ограничение:
Код: plaintext
select * from vizits where fname = 'SOL071119' limit  100 ;

Несколько вопросов:
1. А что Вы хотите получитт Вашему запросу? hint: ORDER BY - таки рулит.
2. А несложно будет бросить не только explain, но и explain analyze.
...
Рейтинг: 0 / 0
LIMIT не использует индекс
    #34977503
_Андрей_М
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ладно, в следующий раз скажу "Интересное счастье привалило".
Я понимаю,что заставить искать по индексу можно. Я не понимаю, почему нужно заставлять.
В какой ситуации поиск с лимитом без индекса будет быстрее поиска с лимитом и с индексом?
Код: plaintext
1.
2.
3.
4.
5.
Bitmap Heap Scan on vizits  (cost= 41711 . 06 .. 648476 . 00  rows= 594815  width= 313 ) (actual time= 367 . 245 .. 976 . 356  rows= 672628  loops= 1 )
  Recheck Cond: ((fname)::text = 'SOL071119'::text)
  ->  Bitmap Index Scan on vizits_fname_nrec  (cost= 0 . 00 .. 41562 . 35  rows= 594815  width= 0 ) (actual time= 357 . 947 .. 357 . 947  rows= 672628  loops= 1 )
        Index Cond: ((fname)::text = 'SOL071119'::text)
Total runtime:  1236 . 856  ms
Код: plaintext
1.
2.
3.
4.
Limit  (cost= 0 . 00 .. 113 . 91  rows= 100  width= 313 ) (actual time= 68374 . 250 .. 72133 . 281  rows= 100  loops= 1 )
  ->  Seq Scan on vizits  (cost= 0 . 00 .. 677567 . 97  rows= 594815  width= 313 ) (actual time= 68374 . 246 .. 72133 . 104  rows= 100  loops= 1 )
        Filter: ((fname)::text = 'SOL071119'::text)
Total runtime:  72133 . 540  ms

Код: plaintext
explain analyze select * from vizits where fname = 'SOL071119' order by fname limit  100 

Код: plaintext
1.
2.
3.
4.
Limit  (cost= 0 . 00 .. 397 . 47  rows= 100  width= 313 ) (actual time= 19 . 148 .. 36 . 173  rows= 100  loops= 1 )
  ->  Index Scan using vizits_fname_nrec on vizits  (cost= 0 . 00 .. 2364190 . 75  rows= 594815  width= 313 ) (actual time= 19 . 146 .. 36 . 090  rows= 100  loops= 1 )
        Index Cond: ((fname)::text = 'SOL071119'::text)
Total runtime:  36 . 305  ms
...
Рейтинг: 0 / 0
LIMIT не использует индекс
    #34980277
Andrey Daeron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Андрей_МЛадно, в следующий раз скажу "Интересное счастье привалило".
Я понимаю,что заставить искать по индексу можно. Я не понимаю, почему нужно заставлять.

Дело в том, что в доках по LIMIT указано, что он без ORDER BY конечно не выдаёт ошибку синтаксиса, но в общем и целом работает как захочет. Отсюда и мой вопрос: "Что Вы хотите получить своим запросом? Что-то конкретное? Или просто несколько записей? Каких-то?". При указании ORDER BY - ситуация явно становится другой, и Вы чётко выраете своё желание. LIMIT без ORDER BY не имеет практической ценности (т.е. придумать можно, но вот на практике...).

_Андрей_М
В какой ситуации поиск с лимитом без индекса будет быстрее поиска с лимитом и с индексом?

В случае если выборка, например, это full table без 1-й записи.
...
Рейтинг: 0 / 0
LIMIT не использует индекс
    #34981155
_Андрей_М
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Понятно. Мне было просто нужно несколько записей, на формат данных посмотреть, и сравнительно долгое ковыряние в базе насторожило.
Full table без одной записи, как мне кажется, имеет не больше практической ценности, чем лимит без сортировки.
...
Рейтинг: 0 / 0
LIMIT не использует индекс
    #34982680
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
в этом примере постгрес считает, что распределение значений 1 и 2 в поле f1 одинаковое - 50%. он не замечает того факта, что физически в файле сначала находится миллион строк со значением 1, а после - с 2.

Код: plaintext
1.
2.
3.
4.
create table t1 ( f1 integer );
create index i1 on t1 ( f1 );
insert into t1 select  1  from generate_series( 1 , 1000000 );
insert into t1 select  2  from generate_series( 1 , 1000000 );
analyze t1;

при этом запрос по IndexScan для 1 и 2 выполняется примерно одинаковое время

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
nalbat=> explain analyze select * from t1 where f1= 1  limit  5 ;
                                                      QUERY PLAN
----------------------------------------------------------------------------------------------------------------------
 Limit  (cost= 0 . 00 .. 0 . 11  rows= 5  width= 4 ) (actual time= 0 . 027 .. 0 . 057  rows= 5  loops= 1 )
   ->  Index Scan using i1 on t1  (cost= 0 . 00 .. 21322 . 22  rows= 952683  width= 4 ) (actual time= 0 . 021 .. 0 . 032  rows= 5  loops= 1 )
         Index Cond: (f1 =  1 )
 Total runtime:  0 . 102  ms
( 4  rows)

nalbat=> explain analyze select * from t1 where f1= 2  limit  5 ;
                                                      QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------
 Limit  (cost= 0 . 00 .. 0 . 11  rows= 5  width= 4 ) (actual time= 0 . 019 .. 0 . 048  rows= 5  loops= 1 )
   ->  Index Scan using i1 on t1  (cost= 0 . 00 .. 23441 . 25  rows= 1047352  width= 4 ) (actual time= 0 . 014 .. 0 . 024  rows= 5  loops= 1 )
         Index Cond: (f1 =  2 )
 Total runtime:  0 . 085  ms
( 4  rows)

постгрес предполагает, что запрос по SeqScan для 1 и 2 будет выполняться тоже одинаковое время, немногим дольше IndexScan.

однако реальное время отличается более чем в 3000 раз, при этом SecScan для 1 оказался немного быстрее чем IndexScan, а для 2 - намного медленнее.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
nalbat=> explain analyze select * from t1 where f1= 1  limit  5 ;
                                                QUERY PLAN
-----------------------------------------------------------------------------------------------------------
 Limit  (cost= 0 . 00 .. 0 . 19  rows= 5  width= 4 ) (actual time= 0 . 017 .. 0 . 047  rows= 5  loops= 1 )
   ->  Seq Scan on t1  (cost= 0 . 00 .. 35811 . 44  rows= 952683  width= 4 ) (actual time= 0 . 012 .. 0 . 024  rows= 5  loops= 1 )
         Filter: (f1 =  1 )
 Total runtime:  0 . 089  ms
( 4  rows)

nalbat=> explain analyze select * from t1 where f1= 2  limit  5 ;
                                                   QUERY PLAN
----------------------------------------------------------------------------------------------------------------
 Limit  (cost= 0 . 00 .. 0 . 17  rows= 5  width= 4 ) (actual time= 343 . 323 .. 343 . 353  rows= 5  loops= 1 )
   ->  Seq Scan on t1  (cost= 0 . 00 .. 35811 . 44  rows= 1047352  width= 4 ) (actual time= 343 . 317 .. 343 . 327  rows= 5  loops= 1 )
         Filter: (f1 =  2 )
 Total runtime:  343 . 392  ms
( 4  rows)

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


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