• Почему PostgreSQL использует неоптимальный план выполнения для простого запроса?

    @yurasek Автор вопроса
    Только после того, как я отметил индекс как кластерный и выполнил команду CLUSTER для упорядочивания данных таблицы, запрос начал выполняться с адекватной скоростью: за 0,066 с.
  • Почему PostgreSQL использует неоптимальный план выполнения для простого запроса?

    @yurasek Автор вопроса
    Следуя Вашему совету решил провести эксперимент в Ubuntu 14.04 LTS x64 правда в виртуальной среде. Процессор был полностью проброшен, выделено 4 Гб ОЗУ, база размером 37 Гб была скопирована на выделенный раздел, таким образом фрагментированность файлов базы исключена. Пришлось повозиться с локалью базы, т.к. клиент pgAdmin ни в какую не хотел подключаться к базе, ссылаясь на неизвестную локаль Russian_Russia.1251. Она была присвоена при создании базы в Windows , а в Ubuntu такой нет. Наверное разработчикам очень сложно было сделать что-то универсальное, но да ладно. Я пробовал найти штатный способ смены локали, но как оказалось таковой нет. Наверное, это опять же сложная задача для разработчиков. Найденный в интернете способ резервного копирования и восстановления базы с новой локалью меня немного озадачил своими временными рамками, да к тому же у меня нет текстовых полей. Пришлось провести небольшой эксперимент: при помощи поиска был найден в папке global файл, содержащий название локали Russian_Russia.1251. Локаль Russian_Russia.1251 была заменена в hex-редакторе на ru_RU.utf8, а оставшиеся символы затёрты нулями. После этого подключение pgAdmin прошло корректно.
    Дальше я решил проверить скорость выполнения запроса вида
    SELECT MAX(time) FROM params WHERE counter_id IN (123, 345);
    Увы, но запрос выполнился за 116 секунд!
    "Aggregate  (cost=139934.30..139934.31 rows=1 width=8)"
    "  ->  Bitmap Heap Scan on params  (cost=908.12..139837.85 rows=38578 width=8)"
    "        Recheck Cond: (counter_id = ANY ('{123,345}'::integer[]))"
    "        ->  Bitmap Index Scan on counter_id_time  (cost=0.00..898.48 rows=38578 width=0)"
    "              Index Cond: (counter_id = ANY ('{123,345}'::integer[]))"

    Таким образом дело не в Windows и shared_buffers, но в чём же тогда?
  • Почему PostgreSQL использует неоптимальный план выполнения для простого запроса?

    @yurasek Автор вопроса
    explain (analyze, buffers) SELECT MAX(time) FROM params WHERE counter_id IN (8888);

    "Result  (cost=4.59..4.60 rows=1 width=0) (actual time=36.492..36.492 rows=1 loops=1)"
    "  Buffers: shared hit=1 read=4"
    "  InitPlan 1 (returns $0)"
    "    ->  Limit  (cost=0.57..4.59 rows=1 width=8) (actual time=36.487..36.487 rows=1 loops=1)"
    "          Buffers: shared hit=1 read=4"
    "          ->  Index Only Scan Backward using counter_id_time on params  (cost=0.57..77534.35 rows=19289 width=8) (actual time=36.486..36.486 rows=1 loops=1)"
    "                Index Cond: ((counter_id = 8888) AND ("time" IS NOT NULL))"
    "                Heap Fetches: 1"
    "                Buffers: shared hit=1 read=4"
    "Planning time: 0.198 ms"
    "Execution time: 36.525 ms"


    explain (analyze, buffers) SELECT MAX(time) FROM params WHERE counter_id IN (8888, 8888);

    "Aggregate  (cost=139934.30..139934.31 rows=1 width=8) (actual time=81536.479..81536.479 rows=1 loops=1)"
    "  Buffers: shared hit=222 read=19201"
    "  ->  Bitmap Heap Scan on params  (cost=908.12..139837.85 rows=38578 width=8) (actual time=50.128..81522.183 rows=19420 loops=1)"
    "        Recheck Cond: (counter_id = ANY ('{8888,8888}'::integer[]))"
    "        Heap Blocks: exact=19343"
    "        Buffers: shared hit=222 read=19201"
    "        ->  Bitmap Index Scan on counter_id_time  (cost=0.00..898.48 rows=38578 width=0) (actual time=47.687..47.687 rows=19420 loops=1)"
    "              Index Cond: (counter_id = ANY ('{8888,8888}'::integer[]))"
    "              Buffers: shared hit=4 read=76"
    "Planning time: 0.202 ms"
    "Execution time: 81536.674 ms"
  • Почему PostgreSQL использует неоптимальный план выполнения для простого запроса?

    @yurasek Автор вопроса
    База работает на Windows 8.1 x64. Процессор Intel i7-4820, оперативной памяти 16 Гб, диск на 3 Тб.
    Сама база сейчас занимает 37 Гб (321 млн записей + индекс по полю counter_id и time).
    Это тестовая база, но имитирует боевую базу на MySQL 5.6.10, которую я планирую оптимизировать или заменить на PostgreSQL, если я приду к пониманию, что PostgreSQL справляется поставленной задачей лучше.
    В таблице params используется ровно 16384 уникальных значений counter_id, которые были добавлены в рэндомном порядке в базу, но с равномерным количеством записей (321000000/16384 ~ 19592). После чего был создан индекс по полям counter_id и time.

    Вот результат запроса explain (analyze, buffers) select max(time) from params where counter_id in (9876, 6789);
    "Aggregate  (cost=139934.30..139934.31 rows=1 width=8) (actual time=132113.630..132113.630 rows=1 loops=1)"
    "  Buffers: shared hit=112 read=39422"
    "  ->  Bitmap Heap Scan on params  (cost=908.12..139837.85 rows=38578 width=8) (actual time=111.489..132081.067 rows=39693 loops=1)"
    "        Recheck Cond: (counter_id = ANY ('{9876,6789}'::integer[]))"
    "        Heap Blocks: exact=39373"
    "        Buffers: shared hit=112 read=39422"
    "        ->  Bitmap Index Scan on counter_id_time  (cost=0.00..898.48 rows=38578 width=0) (actual time=93.849..93.849 rows=39693 loops=1)"
    "              Index Cond: (counter_id = ANY ('{9876,6789}'::integer[]))"
    "              Buffers: shared hit=2 read=159"
    "Planning time: 0.238 ms"
    "Execution time: 132113.965 ms"
  • Почему PostgreSQL использует неоптимальный план выполнения для простого запроса?

    @yurasek Автор вопроса
    Всё оказывается ещё страннее, т.к. запрос
    SELECT MAX(time) FROM params WHERE counter_id IN (4444);
    и
    SELECT MAX(time) FROM params WHERE counter_id IN (4444, 4444);
    выполняются разное время! Первый за 0,034 с, а второй за 80 с!
  • Почему PostgreSQL использует неоптимальный план выполнения для простого запроса?

    @yurasek Автор вопроса
    С конструкцией IN (6001, 15998) запрос действительно лучше и наглядней, спасибо.
    Без analyze params запрос:
    SELECT MAX(time) FROM params WHERE counter_id IN (6001, 15998);

    выполнился за 125 секунд.
    После выполнения analyze params этот запрос выполнился на 0,3 с и закэшировался, но любой последующий запрос с использованием двух произвольных чисел counter_id выполняется где-то за 125 секунд, после чего кэшируется и повторно выполняется за 0,3 с. Таким образом в моём случае analyze params хотя бы помогает кэшировать результаты запроса, но всё равно пока ситуация в моём случае остаётся странной.
  • Почему некорректно работает запрос при использовании UNION в хранимой процедуре в MySQL?

    @yurasek Автор вопроса
    Пока нашёл для себя наиболее оптимальное решение в "одну строку":
    SELECT LEAST(COALESCE(t1, t2), COALESCE(t2, t1)) FROM
     (SELECT MIN(TIME) t1 FROM params WHERE counter_id = 11858 AND time >= 3629232000000) p1,
     (SELECT MAX(TIME) t2 FROM params WHERE counter_id = 11858 AND time <  3629232000000) p2;
  • Почему некорректно работает запрос при использовании UNION в хранимой процедуре в MySQL?

    @yurasek Автор вопроса
    Мне в первую очередь интересна причина такого поведения MySQL. Как мне кажется мой запрос вполне корректный для хранимой процедуры. Я использую MySQL Community Server 5.6.10.1.
  • Почему некорректно работает запрос при использовании UNION в хранимой процедуре в MySQL?

    @yurasek Автор вопроса
    С Вашим запросом у меня не возвращается никакой результат.
    Второй пример у меня используется не как select * from ..., а как select min(t) from ..., т.е. у меня один из запросов между union может вернуть NULL, но мне нужно максимальное значение ниже определённой даты, а если его нет, то минимальное значение выше определённой даты, среди которых я выбираю минимальный результат.
  • Как правильно запускать приложения в терминале Ubuntu 14.10?

    @yurasek Автор вопроса
    Спасибо всем. В официальной русскоязычной документации ничего не сказано про ./, а в англоязычной да.