{"id":36704,"date":"2019-10-31T22:13:15","date_gmt":"2019-10-31T19:13:15","guid":{"rendered":"https:\/\/prohoster.info\/blog\/optimizatsiya-zaprosov-bazy-dannyh-na-primere-b2b-servisa-dlya-stroitelej\/"},"modified":"2019-10-31T22:13:15","modified_gmt":"2019-10-31T19:13:15","slug":"optimizatsiya-zaprosov-bazy-dannyh-na-primere-b2b-servisa-dlya-stroitelej","status":"publish","type":"post","link":"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/optimizatsiya-zaprosov-bazy-dannyh-na-primere-b2b-servisa-dlya-stroitelej","title":{"rendered":"Optimalisatie van databaseverzoeken aan de hand van een voorbeeld van een B2B-service voor bouwbedrijven.","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Hoe kun je het aantal databaseverzoeken met 10 keer vergroten zonder over te stappen naar een krachtigere server en de werking van het systeem te behouden? Ik zal vertellen hoe we de daling van de prestaties van onze database hebben bestreden, hoe we SQL-query's hebben geoptimaliseerd om zoveel mogelijk gebruikers te bedienen zonder de kosten voor rekenkracht te verhogen.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><br \/>\nIk ontwikkel een service voor het beheren van bedrijfsprocessen in bouwbedrijven. Ongeveer 3000 bedrijven werken met ons. Meer dan 10.000 mensen werken elke dag 4-10 uur met ons systeem. Het lost verschillende taken op op het gebied van planning, waarschuwingen, notificaties en validatie\u2026 We maken gebruik van PostgreSQL 9.6. In onze database hebben we ongeveer 300 tabellen en elke dag komen er tot 200 miljoen verzoeken binnen (10.000 verschillende). Gemiddeld hebben we 3-4 duizend verzoeken per seconde, tijdens de meest actieve momenten meer dan 10.000 verzoeken per seconde. Het grootste deel van de verzoeken is OLAP. Toevoegingen, wijzigingen en verwijderingen zijn veel minder, wat betekent dat de OLTP-last relatief klein is. Ik geef deze cijfers om de omvang van ons project te laten zien en te begrijpen hoe nuttig onze ervaring voor jou kan zijn.<\/p>\n<h3>Eerste sc\u00e8ne. Lyrisch<\/h3>\n<p>\nToen we met de ontwikkeling begonnen, dachten we niet echt na over de last die op de database zou komen en wat we zouden doen als de server het niet meer zou trekken. Bij het ontwerpen van de database volgden we de algemene aanbevelingen en probeerden we niet in onze eigen voet te schieten, maar verder dan algemene adviezen zoals 'gebruik geen patroon' gingen we niet. <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Entity%E2%80%93attribute%E2%80%93value_model\">Entity Attribute Values<\/a><\/noindex> we gingen verder. We ontwierpen volgens de beginselen van normalisatie, waarbij we redundantie in gegevens vermeden, en maakten ons geen zorgen over het versnellen van bepaalde verzoeken. Zodra de eerste gebruikers kwamen, stuitten we op prestatieproblemen. Zoals gewoonlijk waren we helemaal niet voorbereid op deze situatie. De eerste problemen waren eenvoudig. Meestal werd alles opgelost door een nieuwe index toe te voegen. Maar er kwam een moment waarop eenvoudige oplossingen niet meer werkten. Ons realiseren dat we niet genoeg ervaring hadden en dat het steeds moeilijker werd om de oorzaak van de problemen te begrijpen, hebben we specialisten ingehuurd die ons hielpen om de server goed in te stellen, monitoring aan te sluiten en ons lieten zien waar we moesten kijken om <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/9.6\/pgstatstatements.html\">statistieken<\/a><\/noindex>.<\/p>\n<h3>Tweede sc\u00e8ne. Statistisch<\/h3>\n<p>\nWe have about 10,000 different queries executed on our database per day. Among these 10,000, there are monsters that run 2-3 million times with an average execution time of 0.1-0.3 milliseconds, and there are queries with an average execution time of 30 seconds that are called 100 times a day.<\/p>\n<p>Optimizing all 10,000 queries was not feasible, so we decided to figure out where to focus our efforts to correctly enhance database performance. After several iterations, we started categorizing the queries by type.<\/p>\n<h4>TOP queries<\/h4>\n<p>\nThese are the heaviest queries that take the most time (total time). These are queries that are either frequently called or queries that take a long time to execute (long and frequent queries have already been optimized in earlier iterations in the speed race). Ultimately, the server spends the most time executing them. It is also important to separate top queries by total execution time and separately by IO time. The optimization methods for such queries vary slightly.<\/p>\n<p>The common practice among all companies is to work with TOP queries. There are only a few, and optimizing even one query can free up 5-10% of resources. However, as the project 'grows up', optimizing TOP queries becomes an increasingly non-trivial task. All simple approaches have already been implemented, and the most 'heaviest' query consumes 'only' 3-5% of resources. If TOP queries collectively take less than 30-40% of the time, you've probably already made efforts to ensure they run quickly, and it's time to move on to optimizing queries from the next group.<br \/>\nThe remaining question is how many top queries to include in this group. I usually take no less than 10 but no more than 20. I try to ensure that the execution time of the first and last query in the TOP group differs by no more than 10 times. That is, if the execution time of the queries drops sharply from 1st place to 10th, I take TOP-10; if the drop is more gradual, I increase the group size to 15 or 20.<br \/>\n<img decoding=\"async\" alt=\"Optimalisatie van databaseverzoeken aan de hand van een voorbeeld van een B2B-service voor bouwbedrijven.\" src=\"\/wp-content\/uploads\/2019\/08\/2a9d9e6053d1aebb71aa213757bd2393.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h4>Middlers (medium)<\/h4>\n<p>\nThese are all the queries that immediately follow TOP, except for the last 5-10%. Usually, the optimization of these queries holds the potential to significantly boost server performance. These queries can account for up to 80%. But even if their share exceeds 50%, it means it's time to take a closer look at them.<\/p>\n<h4>Tail (tail)<\/h4>\n<p>\nZoals eerder vermeld, vinden deze verzoeken aan het einde plaats en kost het 5-10% van de tijd. Je kunt ze vergeten, tenzij je automatische analysetools voor verzoeken gebruikt, dan kan hun optimalisatie ook goedkoop zijn.<\/p>\n<p>Hoe elke groep te evalueren?<\/p>\n<p>Ik gebruik een SQL-query die helpt bij het maken van een dergelijke evaluatie voor PostgreSQL (ik weet zeker dat voor vele andere DBMS's een vergelijkbare query kan worden geschreven).<\/p>\n<p><b class=\"spoiler_title\">SQL-query voor het evalueren van de grootte van de TOP-MEDIUM-TAIL groepen.<\/b><\/p>\n<pre><code class=\"sql\">SELECT sum(time_top) AS sum_top, sum(time_medium) AS sum_medium, sum(time_tail) AS sum_tail\nFROM\n(\n  SELECT CASE WHEN rn &lt;= 20              THEN tt_percent ELSE 0 END AS time_top,\n         CASE WHEN rn &gt; 20 AND rn &lt;= 800 THEN tt_percent ELSE 0 END AS time_medium,\n         CASE WHEN rn &gt; 800              THEN tt_percent ELSE 0 END AS time_tail\n  FROM (\n    SELECT total_time \/ (SELECT sum(total_time) FROM pg_stat_statements) * 100 AS tt_percent, query,\n    ROW_NUMBER () OVER (ORDER BY total_time DESC) AS rn\n    FROM pg_stat_statements\n    ORDER BY total_time DESC\n  ) AS t\n)\nAS ts\n<\/code><\/pre>\n<p>Het resultaat van de query zijn drie kolommen, waarvan elke kolom het percentage tijd bevat dat wordt besteed aan de verwerking van verzoeken uit deze groep. In de query zijn er twee getallen (in mijn geval zijn dat 20 en 800), die de verzoeken van de ene groep van de andere scheiden.<\/p>\n<p>Zo verhouden de aandelen van de verzoeken zich aan het begin van de optimalisatie en nu.<\/p>\n<p><img decoding=\"async\" alt=\"Optimalisatie van databaseverzoeken aan de hand van een voorbeeld van een B2B-service voor bouwbedrijven.\" src=\"\/wp-content\/uploads\/2019\/08\/9c70ad9aba8b835c94729c9dda656eab.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nUit de diagram blijkt dat het aandeel TOP-verzoeken sterk is afgenomen, terwijl de 'gemiddelden' zijn toegenomen.<br \/>\nAanvankelijk waren er duidelijke blunders in de TOP-verzoeken. Na verloop van tijd verdwenen de kinderziekten, het aandeel TOP-verzoeken nam af en het was steeds moeilijker om zware verzoeken te versnellen. <\/p>\n<p><b class=\"spoiler_title\">Om de teksten van de verzoeken te krijgen, gebruiken we de volgende query.<\/b><\/p>\n<pre><code class=\"sql\">SELECT * FROM (\n  SELECT ROW_NUMBER () OVER (ORDER BY total_time DESC) AS rn, total_time \/ (SELECT sum(total_time) FROM pg_stat_statements) * 100 AS tt_percent, query\n  FROM pg_stat_statements\n  ORDER BY total_time DESC\n) AS T\nWHERE\nrn &lt;= 20 -- TOP\n-- rn &gt; 20 AND rn &lt;= 800 -- MEDIUM\n-- rn &gt; 800  -- TAIL\n<\/code><\/pre>\n<p>Hier is een lijst van de meest gebruikte technieken die ons hielpen om de TOP-verzoeken te versnellen:<\/p>\n<ul>\n<li>Herontwerp van het systeem, bijvoorbeeld het herschrijven van de notificatielogica naar message broker in plaats van periodieke verzoeken naar de DB.<\/li>\n<li>Toevoegen of wijzigen van indexen.<\/li>\n<li>Herschrijven van ORM-verzoeken naar pure SQL.<\/li>\n<li>Herschrijven van de logica voor lazy data loading.<\/li>\n<li>Caching via denormalisatie van gegevens. Bijvoorbeeld, we hebben een relatie tussen de tabellen Levering -&gt; Factuur -&gt; Verzoek -&gt; Aanvraag. Dit betekent dat elke levering is verbonden met de aanvraag via andere tabellen. Om niet in elk verzoek alle tabellen te hoeven koppelen, hebben we de verwijzing naar de aanvraag gedupliceerd in de tabel Levering.<\/li>\n<li>Caching van statische tabellen met referenties en zelden veranderende tabellen in het geheugen van de applicatie.<\/li>\n<\/ul>\n<p>\nSoms leidden wijzigingen tot aanzienlijke herontwerpen, maar resulteerden in 5-10% ontlasting van het systeem, wat gerechtvaardigd was. In de loop van de tijd nam de opbrengst echter steeds verder af en werd er steeds serieuzer redesign gevraagd.<\/p>\n<p>Toen richtten we onze aandacht op de tweede groep verzoeken - de mid-tier groep. Deze had veel meer verzoeken, en het leek erop dat de analyse van de hele groep veel tijd zou kosten. De meeste verzoeken bleken echter heel eenvoudig te optimaliseren en veel problemen herhaalden zich tientallen keren in verschillende variaties. Hier zijn enkele voorbeelden van typische optimalisaties die we toepasten op tientallen soortgelijke verzoeken, waardoor elke groep geoptimaliseerde verzoeken de database met 3-5% ontlastte.<\/p>\n<ul>\n<li> In plaats van te controleren op het bestaan van records met COUNT en een volledige tabelscan uit te voeren, gebruiken we voortaan EXISTS.\n <\/li>\n<li>We hebben DISTINCT verwijderd (er is geen algemeen recept, maar soms kan het gemakkelijk worden verwijderd, waardoor de uitvoering van de query 10-100 keer sneller wordt).\n<p>Bijvoorbeeld, in plaats van de query om alle chauffeurs uit een grote bezorgtabel (DELIVERY) te selecteren. <\/p>\n<pre><code class=\"sql\">SELECT DISTINCT P.ID, P.FIRST_NAME, P.LAST_NAME\nFROM DELIVERY D JOIN PERSON P ON D.DRIVER_ID = P.ID\n<\/code><\/pre>\n<p>\nhebben we een query gemaakt voor de relatief kleine tabel PERSON.<\/p>\n<pre><code class=\"sql\">SELECT P.ID, P.FIRST_NAME, P.LAST_NAME\nFROM PERSON\nWHERE EXISTS(SELECT D.ID FROM DELIVERY WHERE D.DRIVER_ID = P.ID)\n<\/code><\/pre>\n<p>\nDan lijkt het misschien alsof we een correlatie subquery gebruikten, maar deze leidt tot een versnelling van meer dan 10 keer.\n <\/li>\n<li>In veel gevallen hebben we helemaal afstand gedaan van COUNT en <br \/>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/www.citusdata.com\/blog\/2016\/10\/12\/count-performance\/#dup_counts_estimated_filtered\">vervangen door het berekenen van een benaderde waarde.<\/a><\/noindex>\n <\/li>\n<li>in plaats van\n<pre><code class=\"sql\">UPPER(s) LIKE JOHN% \n<\/code><\/pre>\n<p>\ngebruik van <\/p>\n<pre><code class=\"sql\">s ILIKE \u201cJohn%\u201d\n<\/code><\/pre>\n<p>\n <\/li>\n<\/ul>\n<p>\nElk specifiek verzoek kon soms 3-1000 keer worden versneld. Ondanks de indrukwekkende cijfers dachten we in het begin dat het geen zin had om een verzoek te optimaliseren dat 10 ms duurde, dat in de top 300 van de zwaarste verzoeken stond en dat in totaal slechts fracties van procenten van de belasting op de database vertegenwoordigde. Maar door hetzelfde recept toe te passen op een groep soortgelijke verzoeken, boeten we enkele procenten terug. Om geen tijd te verliezen met handmatig bekijken van alle honderden verzoeken, hebben we een paar eenvoudige scripts geschreven die met behulp van reguliere expressies soortgelijke verzoeken vonden. Uiteindelijk stelde de automatische zoekfunctie naar groepen verzoeken ons in staat om onze productiviteit verder te verbeteren met bescheiden inspanningen.<\/p>\n<p>We have been working on the same hardware for three years now. The average daily load is around 30%, peaking at 70%. The number of requests and users has increased about tenfold. All of this is thanks to constant monitoring of these query groups TOP-MEDIUM. As soon as a new query appears in the TOP group, we analyze it immediately and try to speed it up. We review the MEDIUM group with query analysis scripts once a week. If we come across new queries that we already know how to optimize, we implement those changes quickly. Sometimes we discover new optimization methods that can be applied to several queries at once. <\/p>\n<p>According to our forecasts, the current server can handle an increase in the number of users by another 3-5 times. However, we still have one ace up our sleeve\u2014we haven't yet switched the SELECT queries to a mirror as recommended. But we consciously avoid doing this because we want to fully exhaust the possibilities of 'smart' optimization before resorting to 'heavy artillery'.<br \/>\nA critical look at the work done may suggest using vertical scaling. Buying a more powerful server instead of wasting specialists' time could be beneficial. Servers can be relatively inexpensive, especially since we haven't yet exhausted the limits of vertical scaling. However, the number of requests has only increased tenfold. Over the years, the system's functionality has grown, leading to a greater variety of queries. The previous functionality is now executed with fewer, more efficient requests due to caching. This means we can confidently multiply by another 5 to obtain the true acceleration factor. Thus, by the most conservative estimates, we can say that acceleration has reached 50 times or more. It would have been more expensive to vertically scale the server by 50 times, especially considering that once an optimization is performed, it operates continuously, while the bill for the rented server comes every month.<br \/>\n<br \/>Bron: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/461071\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041a\u0430\u043a \u0432\u044b\u0440\u0430\u0441\u0442\u0438 \u0432 10 \u0440\u0430\u0437 \u043f\u043e\u0434 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a \u0411\u0414 \u043d\u0435 \u043f\u0435\u0440\u0435\u0435\u0437\u0436\u0430\u044f \u043d\u0430 \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u043e\u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u044b? \u042f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u043c\u044b \u0431\u043e\u0440\u043e\u043b\u0438\u0441\u044c \u0441 \u043f\u0430\u0434\u0435\u043d\u0438\u0435\u043c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043d\u0430\u0448\u0435\u0439 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u0430\u043a \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043b\u0438 SQL \u0437\u0430\u043f\u0440\u043e\u0441\u044b, \u0447\u0442\u043e\u0431\u044b \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0438 \u043d\u0435 \u043f\u043e\u0432\u044b\u0448\u0430\u0442\u044c \u0440\u0430\u0441\u0445\u043e\u0434\u044b \u043d\u0430 \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044b. \u042f \u0434\u0435\u043b\u0430\u044e \u0441\u0435\u0440\u0432\u0438\u0441 \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0431\u0438\u0437\u043d\u0435\u0441 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430\u043c\u0438 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":27493,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-36704","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.3 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041a\u0430\u043a \u0432\u044b\u0440\u0430\u0441\u0442\u0438 \u0432 10 \u0440\u0430\u0437 \u043f\u043e\u0434 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a \u0411\u0414 \u043d\u0435 \u043f\u0435\u0440\u0435\u0435\u0437\u0436\u0430\u044f \u043d\u0430 \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u043e\u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u044b?\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/optimizatsiya-zaprosov-bazy-dannyh-na-primere-b2b-servisa-dlya-stroitelej\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"nl_NL\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 B2B \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0434\u043b\u044f \u0441\u0442\u0440\u043e\u0438\u0442\u0435\u043b\u0435\u0439 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041a\u0430\u043a \u0432\u044b\u0440\u0430\u0441\u0442\u0438 \u0432 10 \u0440\u0430\u0437 \u043f\u043e\u0434 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a \u0411\u0414 \u043d\u0435 \u043f\u0435\u0440\u0435\u0435\u0437\u0436\u0430\u044f \u043d\u0430 \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u043e\u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u044b?\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/optimizatsiya-zaprosov-bazy-dannyh-na-primere-b2b-servisa-dlya-stroitelej\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T19:13:15+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T19:13:15+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Database Query Optimization Using a B2B Service for Builders | ProHoster","description":"How to grow tenfold in the number of database requests without migrating to a more powerful server while maintaining system functionality?","canonical_url":"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/optimizatsiya-zaprosov-bazy-dannyh-na-primere-b2b-servisa-dlya-stroitelej","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"nl_NL","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 B2B \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0434\u043b\u044f \u0441\u0442\u0440\u043e\u0438\u0442\u0435\u043b\u0435\u0439 | ProHoster","og:description":"\u041a\u0430\u043a \u0432\u044b\u0440\u0430\u0441\u0442\u0438 \u0432 10 \u0440\u0430\u0437 \u043f\u043e\u0434 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a \u0411\u0414 \u043d\u0435 \u043f\u0435\u0440\u0435\u0435\u0437\u0436\u0430\u044f \u043d\u0430 \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u043e\u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u044b?","og:url":"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/optimizatsiya-zaprosov-bazy-dannyh-na-primere-b2b-servisa-dlya-stroitelej","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T19:13:15+00:00","article:modified_time":"2019-10-31T19:13:15+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"36704","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-22 04:30:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 01:40:22","updated":"2026-01-22 04:30:19","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/posts\/36704","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/comments?post=36704"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/posts\/36704\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/media\/27493"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/media?parent=36704"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/categories?post=36704"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/tags?post=36704"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}