Найти последнюю временную метку в нескольких таблицах - PullRequest
0 голосов
/ 13 июля 2020

javascript запускает задачу cycli c для мониторинга базы данных, задача (php) просто запрашивает в базе данных последнюю временную метку:

SELECT
    MAX(po.created)::timestamp last_purchase_order_created,
    MAX(po.modified)::timestamp last_purchase_order_modified,
    MAX(jobs.created)::timestamp last_job_created,
    MAX(jobs.modified)::timestamp last_job_modified,
    MAX(companies.created)::timestamp last_company_created,
    MAX(companies.modified)::timestamp last_company_modified,
    MAX(stock.created)::timestamp last_stock_created,
    MAX(stock.modified)::timestamp last_stock_modified
FROM purchase_orders po, jobs, companies, stock;

Это заняло много времени, потому что PHP не является многопоточным, он блокировал и другие запросы. Есть ли способ преодолеть это? Измененный запрос, другой подход в php, немного того и другого?

Это продолжение проблемы: Медленное соединение с Postgresql с использованием PDO

Ответы [ 2 ]

1 голос
/ 13 июля 2020

Запрос UNION, такой как рекомендовал Майк, был бы лучше, но если вы хотите, чтобы этот запрос был быстрым, вам понадобится индекс каждого столбца , который вы берете max из.

Это кажется странным для частого выполнения запроса. Является ли, таким образом, заменой того, что лучше было бы сделать с последовательностью?

Если вам действительно часто нужны эти максимумы, вы можете поддерживать специальную таблицу, которая содержит только эти максимумы и обновляется всякий раз, когда вы вставляете или обновляете строку. Это сэкономит вам много дорогостоящих индексов.

1 голос
/ 13 июля 2020

Когда вы делаете это таким образом, вы создаете декартово произведение для всех этих таблиц, а это очень требовательно для вашего сервера базы данных.

Если вы хотите сделать это в одном запросе, следуйте этому шаблону , что даст вам одну строку для каждой таблицы:

select 'purchase_orders' as table_name, max(created) as last_created, max(modified) as last_modified 
  from purchase_orders
union all
select 'jobs', max(created), max(modified) 
  from jobs
union all
select 'companies', max(created), max(modified)
  from companies
union all
select 'stock', max(created), max(modified)
  from stock

Обычно я бы перевел это на основной язык (PHP, в вашем случае), но если вам нужно сделать это внутри запроса , то должно работать примерно так:

with latest_dates as (
  select 'purchase_orders' as table_name, max(created) as last_created, max(modified) as last_modified 
    from purchase_orders
  union all
  select 'jobs', max(created), max(modified) 
    from jobs
  union all
  select 'companies', max(created), max(modified)
    from companies
  union all
  select 'stock', max(created), max(modified)
    from stock
)
select max(last_created) filter (where table_name = 'purchase_order') as last_purchase_order_created,
       max(last_modified) filter (where table_name = 'purchase_order') as last_purchase_order_modified,
       max(last_created) filter (where table_name = 'job') as last_job_created,
       max(last_modified) filter (where table_name = 'job') as last_job_modified,
       max(last_created) filter (where table_name = 'company') as last_company_created,
       max(last_modified) filter (where table_name = 'company') as last_company_modified,
       max(last_created) filter (where table_name = 'stock') as last_stock_created,
       max(last_modified) filter (where table_name = 'stock') as last_stock_modified
  from latest_dates;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...