У меня есть вопрос о странном (?) Случае, который я обнаружил относительно сортировки в Postgresql (точнее, 10.3).
У меня есть таблица users
со следующими столбцами:
id
- varchar(36)
- идентификатор в формате UUID firstname
- varchar(255)
, lastname
- varchar(255)
.
Созданы следующие индексы:
create unique index users_pkey on users (id);
create index user_firstname on users (firstname);
create index user_lastname on users (lastname);
Теперь рассмотрим два запроса для каждого набора данных.
Я положил втаблица ~ 100 тыс. строк, где firstname
- случайная строка из 10 символов.
1a)
select id, firstname from users order by firstname asc, id asc limit 50;
и план выполнения для этого запроса:
Limit (cost=7665.06..7665.18 rows=50 width=48) (actual time=105.012..105.016 rows=50 loops=1)
-> Sort (cost=7665.06..7915.07 rows=100003 width=48) (actual time=105.012..105.014 rows=50 loops=1)
Sort Key: firstname, id
Sort Method: top-N heapsort Memory: 31kB
-> Seq Scan on users (cost=0.00..4343.03 rows=100003 width=48) (actual time=0.009..21.510 rows=100003 loops=1)
Planning time: 0.066 ms
Execution time: 105.031 ms
1b)
select id, firstname from users order by firstname desc, id desc limit 50;
изменена сортировка - desc вместо asc
и план выполнения для этого запроса:
Limit (cost=7665.06..7665.18 rows=50 width=48) (actual time=105.586..105.590 rows=50 loops=1)
-> Sort (cost=7665.06..7915.07 rows=100003 width=48) (actual time=105.586..105.589 rows=50 loops=1)
Sort Key: firstname DESC, id DESC
Sort Method: top-N heapsort Memory: 31kB
-> Seq Scan on users (cost=0.00..4343.03 rows=100003 width=48) (actual time=0.010..21.670 rows=100003 loops=1)
Planning time: 0.068 ms
Execution time: 105.606 ms
Итакочень хорошоСортировка в обоих направлениях занимает одинаковое количество времени.
Давайте рассмотрим второй набор данных.Я положил в таблицу ~ 100 тыс. Строк, где firstname
- строка в следующем формате: JohnXXXXX, где XXXXX - последовательность чисел, т. Е. John00000, John00001, John00002, John00003, ..., John99998, John99999.
2a)
select id, firstname from users order by firstname asc, id asc limit 50;
и план выполнения этого запроса:
Limit (cost=7665.06..7665.18 rows=50 width=43) (actual time=99.572..99.577 rows=50 loops=1)
-> Sort (cost=7665.06..7915.07 rows=100003 width=43) (actual time=99.572..99.573 rows=50 loops=1)
Sort Key: firstname, id
Sort Method: top-N heapsort Memory: 29kB
-> Seq Scan on users (cost=0.00..4343.03 rows=100003 width=43) (actual time=0.009..23.660 rows=100003 loops=1)
Planning time: 0.064 ms
Execution time: 99.592 ms
2b)
select id, firstname from users order by firstname desc, id desc limit 50;
сортировка изменена - вместо вместо descasc
и план выполнения для этого запроса:
Limit (cost=7665.06..7665.18 rows=50 width=43) (actual time=659.786..659.791 rows=50 loops=1)
-> Sort (cost=7665.06..7915.07 rows=100003 width=43) (actual time=659.785..659.786 rows=50 loops=1)
Sort Key: firstname DESC, id DESC
Sort Method: top-N heapsort Memory: 32kB
-> Seq Scan on users (cost=0.00..4343.03 rows=100003 width=43) (actual time=0.010..21.510 rows=100003 loops=1)
Planning time: 0.066 ms
Execution time: 659.804 ms
Для второго набора данных второй запрос (2b
) медленнее в 7 раз.
Подвести итог:
+----------------+------------+------------+
| Query\Data set | 1 | 2 |
+----------------+------------+------------+
| 1 | 105.031 ms | 99.592 ms |
| 2 | 105.606 ms | 659.804 ms |
+----------------+------------+------------+
И, наконец, мой вопрос.Почему второй запрос для второго набора данных выполняется в 6-7 раз медленнее, чем в остальных случаях?