Postgres as a hunch. We calculate the percentage of import substitution in Highload mode from 1C

Methods for investigating performance problems at the level of PostgreSQL DBMS operation (New section!) :: Problems and solutions :: Methodological support for developers and administrators of 1C:Enterprise 8 (1c.ru)

The Postgres architecture with the necessary views is well shown here

I initially adjusted the parameters in PostgresSQL.conf according to the 1C recommendations and the main ones were already set by the installer (full list using the Show all command) attachment

The distribution vendor immediately installs

# Add settings for extensions here

#Options for 1C:

escape_string_warning = off

standard_conforming_strings = off

shared_preload_libraries="online_analyze, plantuner, pg_stat_statements"

online_analyze.table_type="temporary"

online_analyze.verbose="off"

online_analyze.local_tracking = 'on'

plantuner.fix_empty_table="on" 

online_analyze.enable = on

lc_messages="en_US.utf-8"

I checked and corrected according to the article PostgreSQL settings for working with 1C:Enterprise. Part 2 :: PostgreSQL :: Methodological support for 1C:Enterprise 8 developers and administrators (1c.ru) only

Shared_buffers at 8 GB, and temp_bufffers at 32 MB which is enough for a load test. I left the rest as in the distribution kit, since it makes sense to do further fine tuning after the test on medium loads

Resource analysis using Windows showed that the SSD disk is loaded by a quarter of the possible IOPS, everything is OK with the network, but the processor load with 32 logical processors is under 100%! In windows, it’s good to watch it through Process explorer.

The picture shows how Postgres processes are arranged, they are created approximately equal to the number of testing threads, and if each one loads under 2%, the total load will be 100%. On the subd server 2 processors with 16 cores, hyper threading creates 32 logical processors i.e. loading of one logical processor can be no more than 3.1%

Analysis pg_stat_statements showed that SELECT FASTTRUNCATE and ANALYZE pg_temp.tt* take 76% of the time – is that really it? No, these are service procedures – it can’t be that bad.

Used query

--SELECT pg_stat_statements_reset(); --сброс счетчика
SELECT 
        pss.userid,
        pss.dbid,
        pd.datname as db_name,
        round((pss.total_exec_time + pss.total_plan_time)::numeric, 2) as total_time, 
        pss.calls, 
        round((pss.mean_exec_time+pss.mean_plan_time)::numeric, 2) as mean, 
        round((100 * (pss.total_exec_time + pss.total_plan_time) / sum((pss.total_exec_time + pss.total_plan_time)::numeric) OVER ())::numeric, 2) as cpu_portion_pctg,
        substr(pss.query, 1, 200) short_query
FROM pg_stat_statements pss, pg_database pd 
WHERE pd.oid=pss.dbid
ORDER BY (pss.total_exec_time + pss.total_plan_time)
DESC LIMIT 30;

Decided to switch to debugging and enable Postgres log level via log_min_messages = debug1 and then I noticed that he was standing log_min_messages = error, but the trace logs are huge. everything is written in them! It doesn’t match the documentation had to switch to panic.

Important !!! Make sure that the trace logs do not write anything extra, even if the parameters are set correctly, apparently I stumbled upon some kind of release errors.

Pyrrhic victory for Postgres?

Making sure that logging no longer writes too much. The test was run again. Results by numbers pleased ~ 1500 ORM records per second

For comparison, MS SQL on the same database with the same data 1400 . Difference 7% in favor of Postgres.

However, Postgres has the results of hardware measurements, and the time spent on operators did not please – 40% of the processor time.

Which generates postgresbackend

At the same time, Disk transfers (blue dotted line) do not reach 10 thousand Iops. Queues Current disk queue (brown) length can be said no.

The same base in the same conditions, but on average MS SQL does not reach 30% of the processor load

At the same time, from the side of MS SQL Disk transfers (dashed blue line) there are already almost 10 thousand iops. Current disk queues (brown) length happen. Of course, this does not mean the advantages of MS SQL, just a different architecture.

What does this mean?

If I increase the load from the 1C cluster with only two application servers, we will most likely get that MS SQL has a performance margin per CPU that is a third more than Postgres, which will simply run out of processor resources faster !!! Of course, asynchronous commit will be enabled for both databases to avoid waiting on the transaction log.

Or maybe the current 7%-10% of Postgres winnings will equalize the chances (more on that below)? Or MS SQL under heavy load will rest against Waits on SSD? Intrigue, right?

What did the Elephant do when He came to the Field? Analysis of a “successful” launch.

If you look at Trace using Postgres (see above for inclusion nuances)

Briefly what does 1C do

How do I interpret this

BEGIN TRANSACTION

Starting a transaction

SELECT

… FROM _AccumRg16920 T1 …WHERE ((T1._Fld628 = CAST(0 AS NUMERIC))) AND (T1._RecorderTRef =

Reading the main table of the register Accumulation Register.SUU_Cube of Profits and Losses (dbo._AccumRg16920) , even if we simply execute the .Write() method in replacement mode

SELECT …. FROM _AccumRgAggOptK21501 T1 … WHERE ((T1._Fld628 = CAST(0 AS NUMERIC))) AND (T1._RegID = …

Called multiple times with different parameters

Reading the aggregation network options table Accumulation Ledger.Accum_Profit and Loss Cube ( dbo._AccumRgAggOpt18422). Why do this every time you write?

DELETE FROM _AccumRg16920

WHERE (_AccumRg16920._RecorderTRef … AND ((_AccumRg16920._LineNo >= CAST(1 AS NUMERIC) AND _AccumRg16920._LineNo < CAST(3 AS NUMERIC)))) AND (_AccumRg16920._Fld628 = CAST(0 AS NUMERIC))

Removing the previous set of records from the main table dbo._AccumRg16920

INSERT INTO _AccumRg16920

Inserting a record into the main table of the accumulation register Accumulation Register. SUU_Profit and Loss Cube. One Insert per register entry

COPY pg_temp.tt2…FROM STDIN BINARY

Inserting a record into the pg_temp.tt2 table

INSERT INTO pg_temp.tt3 …SELECT

date_trunc(‘month’,T1._Period),

T1._Fld17029RRef,

T1._Fld16992RRef,

T1._Fld16993RRef,….

FROM pg_temp.tt2 T1

GROUP BY date_trunc(‘month’,T1._Period),

T1._Fld17029RRef,

Counting new revolutions for subsequent updates.

ANALYZE pg_temp.tt3

Collects statistics

UPDATE_AccumRgTn17037SET….

FROM pg_temp.tt3 T2

WHERE (T2._Period = _AccumRgTn17037._Period AND T2._Fld1702…

Updates the turnover table. It is strange why _AccumRgDl _AccumRgBf are not used? If the aggregates are enabled?

SELECT FASTTRUNCATE(‘pg_temp.tt3’)

We clean

SELECT FASTTRUNCATE(‘pg_temp.tt2’)

We clean

SELECT Creation,Modified,Attributes,DataSize,BinaryData FROM Params WHERE FileName = $1

Why do we read the parameters

COMMIT

We see that with everyone!!! calling the .Record() method for the accumulation register 1C is called

ANALYZE pg_temp.tt2” recalculation of statistics on the temporary table 37% time

SELECT FASTTRUNCATE ($1)“truncate temporary tables thirty% time

Everything else is small compared to this. In combination with the initial increased consumption of CPU resources, this can play a negative role in the next stage of increasing the load.

I personally have a lot of questions both for Postgres developers and for 1C.

Can’t the Postgres query plan optimizer work properly without statistics with properly set indexes?

I know for sure that Oracle can do it, but MS SQL with reservations. But in MS SQL this is implemented automatically when the trace flag 2731 is turned on for the required data volumes. What do the 1C developers in Postgres do with every call to .Write() ANALYZE pg_temp.tt* is a so-so solution, although it is somehow justified?

Why isn’t FASTTRUNCATE so fast?

Judging by the description, it was made specifically for 1C https://postgrespro.ru/docs/postgrespro/15/fasttrun this is super – it means 1C is a respected client of Postgres developers. But 30% of the time? I understand that 1C uses temporary tables too actively, but we all understand for a declarative language a temporary table is just an analogue of a variable (remember what relational algebra and relational calculus are) in a query package, therefore both MS SQL and Oracle develop the functionality of temporary tables.

How to determine in Postgres what CPU time is spent on if you do not take the queries themselves?

From the test it can be seen that Postgres loads the processor by 35-40% and MS SQL by 20-30%, which means that with a higher Highload, Postgres will be the first to leave the race. What is this difference spent on? I did not find a way to analyze this, for example, enabling logging leads to 100% CPU usage, but this is not visible from the pg_* views.

Help Postgres beat MS SQL

Formally, the average load import substitution test for medium load passed Postgres with a slight advantage. But a detailed analysis shows that the increase in load will not be in favor of Postgres, with a high probability. When viewed from the side of Oracle and MS SQL, a competing DBMS should be comparable in terms of capabilities and necessarily better in some areas. But the analysis of the 1C code shows the presence of a vulnerability. Of course, I don’t know all the magic in Postgres and the intrigue remains, but I hope they will tell me how to solve or compensate for these problems. See you on our telegram channel t.me/Chat1CUnlimited There is no choice, only Postgres forward.

PS In the meantime, regularly make Image installations of MS SQL, it can still provide a performance margin for a long time without changing equipment.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *