Еще проблема Qt в том, что его компоненты (виджеты, сеть, потоки и т. д.) хотя и разделены между собой, но для коммуникации с ними (компонентами) используется общий сигнал/слотовый механизм. Т.е. если не подключать сторонние библиотеки (asio, tbb и прочее), всё выглядит целостно, в противном случае нужно или делать свои wrapper-ы для коммуникации с ними или оставлять мешанину функций-адаптеров на виду. Было бы неплохо иметь альтернативный архитектурный вариант, тот же паттерн observer или listener.
К слову, на GitHub есть бенчмарки разных сигнально-слотовых реализаций, возможно что-то заинтересует. Некоторые реализации (к примеру, lsignal) приспособлены к многопоточности.
Извлечь указатель на sqlite3* из QVariant можно и через обычный static_cast, что, кстати, и рекомендуется в приведенной вами ссылке на документацию. Почему извлекаете именно через макросы Q_DECLARE_*?
В связи с чем связано использование классов std::mutex и std::lock_quard, если существуют аналогичные в Qt QMutex и QMutexLocker? Если дело в накладных расходах, то, возможно, стоило бы использовать и std::ofstream вместо QFile.
Интересует один момент, связанный с операциями в абзаце с примером протокола MESI, номер операции #1. Так как при чтении CPU 0 данных из памяти по адресу 0 в других CPU еще нет кеш-линий с этим адресом, то мне кажется, что состояние этой кеш-линии в CPU 0 должно быть всё же Exclusive, а не Shared. Это опечатка или я не совсем правильно понял этот момент? Смущает, что в оригинале статьи тоже Shared.
Мониторинг текущих запросов к базе
Хочу отметить сущестование параметра track_activity_query_size, который увеличивает размер, отводимый под хранение выполняющегося запроса
выдержка из документации
Specifies the number of bytes reserved to track the currently executing command for each active session, for the pg_stat_activity.query field. The default value is 1024. This parameter can only be set at server start.
NULL и уникальные индексы
Также, если количество столбцов превышает максимально допустимое для индекса (по умолчанию, 32), уникальный индекс можно построить по хешу результата их конкатенации:
CREATE UNIQUE INDEX idx_name_unique ON foobar USING btree ( md5 ( field_one::text || field_two::text ) );
Обработка дубликатов
Если необходимо избавится от уже существующих дубликатов, может помочь такой запрос (id — PK, field_one, field_two — столбцы, по которым необходимо построить уникальный индекс):
DELETE FROM foobar
WHERE id IN
(
SELECT unnest ( ( array_agg ( id ) ) [2:9999999] )
FROM foobar
GROUP BY field_one, field_two
HAVING count ( * ) > 1
);
Для формирования JSON из элемента, массива или записи предусмотрен ряд функций. Для установки некоторого поля в данных JSON подойдёт такая пользовательская функция:
Скрытый текст
CREATE OR REPLACE FUNCTION fn_set_json_key ( v_data json, v_key text, v_value anyelement )
RETURNS json AS
$BODY$
SELECT coalesce
(
(
SELECT
(
'{' || string_agg ( to_json ( key ) || ':' || value, ',' ) || '}'
)
FROM
(
SELECT *
FROM json_each ( v_data )
WHERE key != v_key
UNION ALL
SELECT v_key, to_json ( v_value )
) AS fields
), '{}'
)::json;
$BODY$
LANGUAGE SQL IMMUTABLE;
Для операций с отдельным элементом массива можно придумать что-то аналогичное.
Хочу отметить сущестование параметра track_activity_query_size, который увеличивает размер, отводимый под хранение выполняющегося запроса
NULL и уникальные индексы
Также, если количество столбцов превышает максимально допустимое для индекса (по умолчанию, 32), уникальный индекс можно построить по хешу результата их конкатенации:
Обработка дубликатов
Если необходимо избавится от уже существующих дубликатов, может помочь такой запрос (id — PK, field_one, field_two — столбцы, по которым необходимо построить уникальный индекс):
Для операций с отдельным элементом массива можно придумать что-то аналогичное.