ΠœΠ΅Ρ‚ΠΎΠ΄ΠΈ Π·Π° оптимизация Π½Π° LINQ заявкитС Π² C#.NET

Π’ΡŠΠ²Π΅Π΄Π΅Π½ΠΈΠ΅

Π’ Ρ‚Π°Π·ΠΈ статия бяха Ρ€Π°Π·Π³Π»Π΅Π΄Π°Π½ΠΈ някои ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΈ Π·Π° оптимизация LINQ заявки.
Π’ΡƒΠΊ Ρ‰Π΅ прСдставим ΠΎΡ‰Π΅ някои ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ΠΈ Π·Π° оптимизация Π½Π° ΠΊΠΎΠ΄Π°, ΡΠ²ΡŠΡ€Π·Π°Π½ΠΈ с LINQ заявкитС.

Π˜Π·Π²Π΅ΡΡ‚Π½ΠΎ Π΅, Ρ‡Π΅ LINQ(Language-Integrated Query) β€” Ρ‚ΠΎΠ²Π° Π΅ прост ΠΈ ΡƒΠ΄ΠΎΠ±Π΅Π½ Π΅Π·ΠΈΠΊ Π·Π° заявки към ΠΈΠ·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ Π½Π° Π΄Π°Π½Π½ΠΈ.

И LINQ to SQL Π΅ тСхнология Π·Π° Π΄ΠΎΡΡ‚ΡŠΠΏ Π΄ΠΎ Π΄Π°Π½Π½ΠΈ Π² Π‘Π£Π‘Π”. Π’ΠΎΠ²Π° Π΅ ΠΌΠΎΡ‰Π΅Π½ инструмСнт Π·Π° Ρ€Π°Π±ΠΎΡ‚Π° с Π΄Π°Π½Π½ΠΈ, ΠΏΡ€ΠΈ ΠΊΠΎΠΉΡ‚ΠΎ Ρ‡Ρ€Π΅Π· Π΄Π΅ΠΊΠ»Π°Ρ€Π°Ρ‚ΠΈΠ²Π΅Π½ Π΅Π·ΠΈΠΊ сС ΠΈΠ·Π³Ρ€Π°ΠΆΠ΄Π°Ρ‚ заявки, ΠΊΠΎΠΈΡ‚ΠΎ слСд Ρ‚ΠΎΠ²Π° Ρ‰Π΅ сС ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ²Π°Ρ‚ Π² SQL заявки ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π° ΠΈ Ρ‰Π΅ сС ΠΈΠ·ΠΏΡ€Π°Ρ‰Π°Ρ‚ Π½Π° ΡΡŠΡ€Π²ΡŠΡ€ Π½Π° Π±Π°Π·ΠΈ Π΄Π°Π½Π½ΠΈ Π·Π° изпълнСниС. Π’ нашия случай ΠΏΠΎΠ΄ Π‘Π£Π‘Π” Ρ€Π°Π·Π±ΠΈΡ€Π°ΠΌΠ΅ MS SQL Server.

Π’ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‚ΠΎΠ²Π°, LINQ заявкитС Π½Π΅ сС ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ²Π°Ρ‚ Π² ΠΎΠΏΡ‚ΠΈΠΌΠ°Π»Π½ΠΎ написани SQL заявки, ΠΊΠΎΠΈΡ‚ΠΎ Π±ΠΈ могъл Π΄Π° напишС ΠΎΠΏΠΈΡ‚Π΅Π½ DBA с всички нюанси Π½Π° оптимизацията SQL заявки:

  1. ΠΎΠΏΡ‚ΠΈΠΌΠ°Π»Π½ΠΈ съСдинСния (JOIN) ΠΈ Ρ„ΠΈΠ»Ρ‚Ρ€ΠΈΡ€Π°Π½Π΅ Π½Π° Ρ€Π΅Π·ΡƒΠ»Ρ‚Π°Ρ‚ΠΈΡ‚Π΅ (WHERE)
  2. мноТСство нюанси Π² ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° съСдинСния ΠΈ Π³Ρ€ΡƒΠΏΠΎΠ²ΠΈ условия
  3. мноТСство Π²Π°Ρ€ΠΈΠ°Ρ†ΠΈΠΈ Π² замСстванСто Π½Π° условия IN Π½Π° EXISTSΠΈ NOT IN, Π½Π° EXISTS
  4. ΠΏΡ€ΠΎΠΌΠ΅ΠΆΠ΄ΡƒΡ‚ΡŠΡ‡Π½ΠΎ ΠΊΠ΅ΡˆΠΈΡ€Π°Π½Π΅ Π½Π° Ρ€Π΅Π·ΡƒΠ»Ρ‚Π°Ρ‚ΠΈΡ‚Π΅ Ρ‡Ρ€Π΅Π· Π²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΈ Ρ‚Π°Π±Π»ΠΈΡ†ΠΈ, CTE, Ρ‚Π°Π±Π»ΠΈΡ†ΠΈ ΠΏΡ€ΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈ
  5. ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° ΠΏΡ€Π΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΠ΅ (OPTION) с указания ΠΈ Ρ‚Π°Π±Π»ΠΈΡ‡Π½ΠΈ Ρ…ΠΈΠ½Ρ‚ΠΎΠ²Π΅ WITH (…)
  6. ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° индСксируСми прСдставлСния, ΠΊΠ°Ρ‚ΠΎ Π΅Π΄Π½ΠΎ ΠΎΡ‚ срСдствата Π΄Π° сС ΠΈΠ·Π±Π°Π²ΠΈΠΌ ΠΎΡ‚ ΠΈΠ·Π»ΠΈΡˆΠ½ΠΈΡ‚Π΅ чСтСния Π½Π° Π΄Π°Π½Π½ΠΈ ΠΏΡ€ΠΈ извличания

ΠžΡΠ½ΠΎΠ²Π½ΠΈΡ‚Π΅ Ρ‚ΡŠΠ½ΠΊΠΈ мСста Π½Π° производитСлността, ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈ SQL заявки ΠΏΡ€ΠΈ компилация LINQ заявки са:

  1. консолидацията Π½Π° цСлия ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΡŠΠΌ Π·Π° ΠΈΠ·Π²Π»ΠΈΡ‡Π°Π½Π΅ Π½Π° Π΄Π°Π½Π½ΠΈ Π² Π΅Π΄Π½Π° заявка
  2. Π΄ΡƒΠ±Π»ΠΈΡ€Π°Π½Π΅Ρ‚ΠΎ Π½Π° ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ‡Π½ΠΈ Π±Π»ΠΎΠΊΠΎΠ²Π΅ ΠΊΠΎΠ΄, ΠΊΠΎΠ΅Ρ‚ΠΎ Π² ΠΊΡ€Π°ΠΉΠ½Π° смСтка Π²ΠΎΠ΄ΠΈ Π΄ΠΎ ΠΌΠ½ΠΎΠ³ΠΎΠΊΡ€Π°Ρ‚Π½ΠΈ излишни чСтСния Π½Π° Π΄Π°Π½Π½ΠΈ
  3. Π³Ρ€ΡƒΠΏΠΈ ΠΌΠ½ΠΎΠ³ΠΎΡΡŠΡΡ‚Π°Π²Π½ΠΈ условия (логичСски Β«ΠΈΒ» ΠΈ Β«ΠΈΠ»ΠΈΒ») β€” AND ΠΈ OR, съСдинявайки сС Π² слоТни условия, Π²ΠΎΠ΄ΠΈ Π΄ΠΎ Ρ‚ΠΎΠ²Π°, Ρ‡Π΅ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ‚ΠΎΡ€ΡŠΡ‚, ΠΈΠΌΠ°ΠΉΠΊΠΈ подходящи Π½Π΅ΠΊΠ»ΡŠΡΡ‚Π΅Ρ€ΠΈΠ·ΠΎΠ²Π°Π½ΠΈ индСкси, ΠΏΠΎ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΈΡ‚Π΅ ΠΏΠΎΠ»Π΅Ρ‚Π°, Π² ΠΊΡ€Π°ΠΉΠ½Π° смСтка всС ΠΏΠ°ΠΊ Π·Π°ΠΏΠΎΡ‡Π²Π° Π΄Π° ΠΏΡ€Π°Π²ΠΈ сканиранС ΠΏΠΎ кластСрСн индСкс (INDEX SCAN) ΠΏΠΎ Π³Ρ€ΡƒΠΏΠΈ условия
  4. Π΄ΡŠΠ»Π±ΠΎΠΊΠ°Ρ‚Π° влоТСност Π½Π° подзаявкитС ΠΏΡ€Π°Π²ΠΈ ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ°Ρ‚ΠΈΡ‡Π½ΠΎ Ρ€Π°Π·ΡˆΠΈΡ„Ρ€ΠΎΠ²Π°Π½Π΅Ρ‚ΠΎ SQL инструкции ΠΈ Ρ€Π°Π·Π±ΠΎΡ€ΡŠΡ‚ Π½Π° ΠΏΠ»Π°Π½Π° Π·Π° заявки ΠΎΡ‚ страна Π½Π° Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΡ†ΠΈΡ‚Π΅ ΠΈ DBA

ΠœΠ΅Ρ‚ΠΎΠ΄ΠΈ Π·Π° оптимизация

Π‘Π΅Π³Π° Ρ‰Π΅ ΠΏΡ€Π΅ΠΌΠΈΠ½Π΅ΠΌ Π΄ΠΈΡ€Π΅ΠΊΡ‚Π½ΠΎ към ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΈΡ‚Π΅ Π·Π° оптимизация.

1) Π”ΠΎΠΏΡŠΠ»Π½ΠΈΡ‚Π΅Π»Π½ΠΎ индСксиранС

Най-Π΄ΠΎΠ±Ρ€Π΅ Π΅ Π΄Π° Ρ€Π°Π·Π³Π»Π΅ΠΆΠ΄Π°Ρ‚Π΅ Ρ„ΠΈΠ»Ρ‚Ρ€ΠΈΡ‚Π΅ Π½Π° основнитС Ρ‚Π°Π±Π»ΠΈΡ†ΠΈ Π½Π° ΠΈΠ·Π²Π°Π΄ΠΊΠ°Ρ‚Π°, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ ΠΌΠ½ΠΎΠ³ΠΎ чСсто цСлият Π·Π°ΠΏΠΈΡ‚ сС ΠΈΠ·Π³Ρ€Π°ΠΆΠ΄Π° ΠΎΠΊΠΎΠ»ΠΎ Π΅Π΄Π½Π°-Π΄Π²Π΅ основни Ρ‚Π°Π±Π»ΠΈΡ†ΠΈ (заявки-люди-ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ) ΠΈ с стандартСн Π½Π°Π±ΠΎΡ€ ΠΎΡ‚ условия (IsClosed, Canceled, Enabled, Status). Π’Π°ΠΆΠ½ΠΎ Π΅ Π·Π° установСнитС ΠΈΠ·Π²Π°Π΄ΠΊΠΈ Π΄Π° ΡΡŠΠ·Π΄Π°Π΄Π΅Ρ‚Π΅ ΡΡŠΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²Π°Ρ‰ΠΈ индСкси.

Π’ΠΎΠ²Π° Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ ΠΈΠΌΠ° смисъл, ΠΊΠΎΠ³Π°Ρ‚ΠΎ ΠΈΠ·Π±ΠΎΡ€ΡŠΡ‚ ΠΏΠΎ Ρ‚Π΅Π·ΠΈ ΠΏΠΎΠ»Π΅Ρ‚Π° Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»Π½ΠΎ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π°Π²Π° Π²ΡŠΡ€Π½Π°Ρ‚ΠΎΡ‚ΠΎ мноТСство ΠΎΡ‚ запитвания.

НапримСр, ΠΈΠΌΠ°ΠΌΠ΅ 500000 заявки. Π’ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‚ΠΎΠ²Π°, Π°ΠΊΡ‚ΠΈΠ²Π½ΠΈΡ‚Π΅ заявки са само 2000 записа. Π’ΠΎΠ³Π°Π²Π° ΠΏΡ€Π°Π²ΠΈΠ»Π½ΠΎ подбраният индСкс Ρ‰Π΅ Π½ΠΈ ΠΈΠ·Π±Π°Π²ΠΈ ΠΎΡ‚ INDEX SCAN ΠΏΠΎ голямата Ρ‚Π°Π±Π»ΠΈΡ†Π° ΠΈ Ρ‰Π΅ Π½ΠΈ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈ Π±ΡŠΡ€Π·ΠΎ Π΄Π° ΠΈΠ·Π±Π΅Ρ€Π΅ΠΌ Π΄Π°Π½Π½ΠΈ Ρ‡Ρ€Π΅Π· нСкластСризиран индСкс.

Π‘ΡŠΡ‰ΠΎ Ρ‚Π°ΠΊΠ°, Π½Π΅Π΄ΠΎΡΡ‚ΠΈΠ³ΡŠΡ‚ Π½Π° индСкси ΠΌΠΎΠΆΠ΅ Π΄Π° бъдС ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΡ†ΠΈΡ€Π°Π½ Ρ‡Ρ€Π΅Π· подсказки ΠΏΡ€ΠΈ Π°Π½Π°Π»ΠΈΠ· Π½Π° ΠΏΠ»Π°Π½ΠΎΠ²Π΅Ρ‚Π΅ Π½Π° запитвания ΠΈΠ»ΠΈ ΡΡŠΠ±ΠΈΡ€Π°Π½Π΅ Π½Π° статистики ΠΎΡ‚ систСмни прСдставлСния. MS SQL Server:

  1. sys.dm_db_missing_index_groups
  2. sys.dm_db_missing_index_group_stats
  3. sys.dm_db_missing_index_details

Всички Π΄Π°Π½Π½ΠΈ ΠΎΡ‚ прСдставлСнията ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Ρ‚ информация Π·Π° липсващи индСкси, с ΠΈΠ·ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ Π½Π° пространствСни индСкси.

Π’ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‚ΠΎΠ²Π°, индСкситС ΠΈ ΠΊΠ΅ΡˆΠΈΡ€Π°Π½Π΅Ρ‚ΠΎ чСсто са ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΈ Π·Π° справянС с послСдствията ΠΎΡ‚ слабо написани LINQ заявки ΠΈ SQL заявки.

ΠšΠ°ΠΊΡ‚ΠΎ ΠΏΠΎΠΊΠ°Π·Π²Π° суровата бизнСс ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠ°, чСсто Π΅ Π²Π°ΠΆΠ½ΠΎ Ρ€Π΅Π°Π»ΠΈΠ·ΠΈΡ€Π°Π½Π΅Ρ‚ΠΎ Π½Π° бизнСс Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π² ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈ сроковС. И Π·Π°Ρ‚ΠΎΠ²Π° чСсто Ρ‚Π΅ΠΆΠΊΠΈ запитвания сС ΠΏΡ€Π΅Ρ…Π²ΡŠΡ€Π»ΡΡ‚ във Ρ„ΠΎΠ½ΠΎΠ² Ρ€Π΅ΠΆΠΈΠΌ с ΠΊΠ΅ΡˆΠΈΡ€Π°Π½Π΅.

ΠžΡ‚Ρ‡Π°ΡΡ‚ΠΈ Ρ‚ΠΎΠ²Π° Π΅ ΠΎΠΏΡ€Π°Π²Π΄Π°Π½ΠΎ, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ Π½Π° потрСбитСля Π½Π΅ Π²ΠΈΠ½Π°Π³ΠΈ ΠΌΡƒ трябват Π½Π°ΠΉ-Π½ΠΎΠ²ΠΈΡ‚Π΅ Π΄Π°Π½Π½ΠΈ ΠΈ сС постига ΠΏΡ€ΠΈΠ΅ΠΌΠ»ΠΈΠ² Π½ΠΈΠ²ΠΎ Π½Π° отговорност ΠΎΡ‚ потрСбитСлския интСрфСйс.

Π’ΠΎΠ·ΠΈ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ позволява Π΄Π° сС Ρ€Π΅ΡˆΠ°Ρ‚ бизнСс запитвания, Π½ΠΎ Π² ΠΊΡ€Π°ΠΉΠ½Π° смСтка намалява СфСктивността Π½Π° ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΎΠ½Π½Π°Ρ‚Π° систСма, просто ΠΎΡ‚Π»Π°Π³Π°ΠΉΠΊΠΈ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡΡ‚Π° Π½Π° ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠΈΡ‚Π΅.

Π‘ΡŠΡ‰ΠΎ Ρ‚Π°ΠΊΠ°, трябва Π΄Π° сС ΠΏΠΎΠΌΠ½ΠΈ, Ρ‡Π΅ ΠΏΡ€ΠΈ Ρ‚ΡŠΡ€ΡΠ΅Π½Π΅Ρ‚ΠΎ Π½Π° Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΈΡ‚Π΅ Π½ΠΎΠ²ΠΈ индСкси, прСдлоТСнията MS SQL Π·Π° оптимизация ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° Π±ΡŠΠ΄Π°Ρ‚ Π½Π΅ΠΊΠΎΡ€Π΅ΠΊΡ‚Π½ΠΈ, Π²ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»Π½ΠΎ ΠΏΡ€ΠΈ слСднитС условия:

  1. Π°ΠΊΠΎ Π²Π΅Ρ‡Π΅ ΡΡŠΡ‰Π΅ΡΡ‚Π²ΡƒΠ²Π°Ρ‚ индСкси с ΠΏΠΎΠ΄ΠΎΠ±Π΅Π½ Π½Π°Π±ΠΎΡ€ ΠΎΡ‚ ΠΏΠΎΠ»Π΅Ρ‚Π°
  2. Π°ΠΊΠΎ ΠΏΠΎΠ»Π΅Ρ‚Π°Ρ‚Π° Π² Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π° Π½Π΅ ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° Π±ΡŠΠ΄Π°Ρ‚ индСксни ΠΏΠΎΡ€Π°Π΄ΠΈ ограничСния Π½Π° индСксиранСто (ΠΏΠΎ-ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎ Π·Π° Ρ‚ΠΎΠ²Π° Π΅ описано Ρ‚ΡƒΠΊ).

2) ОбСдинСниС Π½Π° Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚ΠΈΡ‚Π΅ Π² Π΅Π΄ΠΈΠ½ Π½ΠΎΠ² Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚

Понякога някои ΠΏΠΎΠ»Π΅Ρ‚Π° ΠΎΡ‚ Π΅Π΄Π½Π° Ρ‚Π°Π±Π»ΠΈΡ†Π°, ΠΏΠΎ ΠΊΠΎΠΈΡ‚ΠΎ сС изпълнява Π³Ρ€ΡƒΠΏΠ° условия, ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° Π±ΡŠΠ΄Π°Ρ‚ Π·Π°ΠΌΠ΅Π½Π΅Π½ΠΈ с Π²ΡŠΠ²Π΅ΠΆΠ΄Π°Π½Π΅Ρ‚ΠΎ Π½Π° Π΅Π΄Π½ΠΎ Π½ΠΎΠ²ΠΎ ΠΏΠΎΠ»Π΅.

ОсобСно Π°ΠΊΡ‚ΡƒΠ°Π»Π½ΠΎ Π΅ Π·Π° ΡΡŠΡΡ‚ΠΎΡΠ½ΠΈΡ, ΠΊΠΎΠΈΡ‚ΠΎ ΠΏΠΎ Ρ‚ΠΈΠΏ ΠΎΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΎ са ΠΈΠ»ΠΈ Π±ΠΈΡ‚ΠΎΠ²ΠΈ, ΠΈΠ»ΠΈ Ρ†Π΅Π»ΠΈ числа.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€:

IsClosed = 0 И Canceled = 0 И Enabled = 0 сС замСня с Status = 1.

Π’ΡƒΠΊ сС въвСТда цяло число Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚ Status, осигурСно ΠΎΡ‚ ΠΏΠΎΠΏΡŠΠ»Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° Ρ‚Π΅Π·ΠΈ статуси Π² Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π°. Π‘Π»Π΅Π΄ Ρ‚ΠΎΠ²Π° сС ΠΏΡ€ΠΎΠ²Π΅ΠΆΠ΄Π° индСксиранС Π½Π° Ρ‚ΠΎΠ·ΠΈ Π½ΠΎΠ² Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚.

Π’ΠΎΠ²Π° Π΅ основно Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ Π½Π° ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° с производитСлността, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ Π½ΠΈΠ΅ ΠΈΠ·Π²ΠΈΠΊΠ²Π°ΠΌΠ΅ Π΄Π°Π½Π½ΠΈ Π±Π΅Π· излишни изчислСния.

3) Мateralизация Π½Π° прСдставлСниС

Π—Π° съТалСниС, Π² LINQ запитванията Π½Π΅ ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ Π΄ΠΈΡ€Π΅ΠΊΡ‚Π½ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π²ΠΈ Ρ‚Π°Π±Π»ΠΈΡ†ΠΈ, CTE ΠΈ Ρ‚Π°Π±Π»ΠΈΡ‡Π½ΠΈ ΠΏΡ€ΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈ.

Π’ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‚ΠΎΠ²Π°, ΡΡŠΡ‰Π΅ΡΡ‚Π²ΡƒΠ²Π° ΠΎΡ‰Π΅ Π΅Π΄ΠΈΠ½ Π½Π°Ρ‡ΠΈΠ½ Π·Π° оптимизация Π² Ρ‚ΠΎΠ·ΠΈ случай β€” индСксируСми прСдставлСния.

Π“Ρ€ΡƒΠΏΠ°Ρ‚Π° условия (ΠΎΡ‚ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° ΠΏΠΎ-Π³ΠΎΡ€Π΅) IsClosed = 0 И Canceled = 0 И Enabled = 0 (ΠΈΠ»ΠΈ Π½Π°Π±ΠΎΡ€ ΠΎΡ‚ Π΄Ρ€ΡƒΠ³ΠΈ ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΈ условия) става Π΄ΠΎΠ±ΡŠΡ€ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ Π·Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅Ρ‚ΠΎ ΠΈΠΌ Π² индСксируСмо прСдставлСниС, ΠΊΠ΅ΡˆΠΈΡ€Π°ΠΉΠΊΠΈ малък срСз Π΄Π°Π½Π½ΠΈ ΠΎΡ‚ голямо мноТСство.

Но ΠΈΠΌΠ° Ρ€Π΅Π΄ΠΈΡ†Π° ограничСния ΠΏΡ€ΠΈ матСриализацията Π½Π° прСдставлСнията:

  1. ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° подзапитвания, прСдлоТСния EXISTS трябва Π΄Π° сС замСнят с JOIN
  2. Π½Π΅ ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ прСдлоТСния UNION, UNION ALL, EXCEPTION, INTERSECT
  3. Π½Π΅ ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ Ρ‚Π°Π±Π»ΠΈΡ‡Π½ΠΈ подсказки ΠΈ прСдлоТСния OPTION
  4. няма Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ Π·Π° Ρ€Π°Π±ΠΎΡ‚Π° с Ρ†ΠΈΠΊΠ»ΠΈ
  5. нСвъзмоТно Π΅ Π΄Π° сС ΠΈΠ·Π²Π΅ΠΆΠ΄Π°Ρ‚ Π΄Π°Π½Π½ΠΈ Π² Π΅Π΄Π½ΠΎ прСдставлСниС ΠΎΡ‚ Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΈ Ρ‚Π°Π±Π»ΠΈΡ†ΠΈ

Π’Π°ΠΆΠ½ΠΎ Π΅ Π΄Π° Π·Π°ΠΏΠΎΠΌΠ½ΠΈΡ‚Π΅, Ρ‡Π΅ Ρ€Π΅Π°Π»Π½Π°Ρ‚Π° ΠΏΠΎΠ»Π·Π° ΠΎΡ‚ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° индСксируСмо прСдставлСниС ΠΌΠΎΠΆΠ΅ Π΄Π° бъдС постигната Π²ΡΡŠΡ‰Π½ΠΎΡΡ‚ само ΠΏΡ€ΠΈ Π½Π΅Π³ΠΎΠ²ΠΎΡ‚ΠΎ индСксиранС.

Но ΠΏΡ€ΠΈ ΠΈΠ·Π²ΠΈΠΊΠ²Π°Π½Π΅ Π½Π° прСдставлСниСто, Ρ‚Π΅Π·ΠΈ индСкси ΠΌΠΎΠΆΠ΅ Π΄Π° Π½Π΅ сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚, Π° Π·Π° явното ΠΈΠΌ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π΄Π° сС ΡƒΠΊΠ°Π·Π²Π° WITH (NOEXPAND).

Въй ΠΊΠ°Ρ‚ΠΎ Π² LINQ запитванията Π½Π΅ ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° сС опрСдСлят Ρ‚Π°Π±Π»ΠΈΡ‡Π½ΠΈ подсказки, Π·Π°Ρ‚ΠΎΠ²Π° трябва Π΄Π° сС Π½Π°ΠΏΡ€Π°Π²ΠΈ ΠΎΡ‰Π΅ Π΅Π΄Π½ΠΎ прСдставлСниС β€” 'ΠΎΠ±Π²ΠΈΠ²ΠΊΠ°' ΠΎΡ‚ слСдния Π²ΠΈΠ΄:

CREATE VIEW Π˜ΠœΠ•_прСдставлСния AS SELECT * FROM MAT_VIEW WITH (NOEXPAND);

4) ИзползванС Π½Π° Ρ‚Π°Π±Π»ΠΈΡ‡Π½ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ

ЧСсто Π² LINQ запитванията Π³ΠΎΠ»Π΅ΠΌΠΈ Π±Π»ΠΎΠΊΠΎΠ²Π΅ подзапитвания ΠΈΠ»ΠΈ Π±Π»ΠΎΠΊΠΎΠ²Π΅, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‰ΠΈ прСдставлСния със слоТна структура, оформят ΠΎΠΊΠΎΠ½Ρ‡Π°Ρ‚Π΅Π»Π½ΠΎ Π·Π°ΠΏΠΈΡ‚Π²Π°Π½Π΅ с ΠΌΠ½ΠΎΠ³ΠΎ слоТна ΠΈ Π½Π΅ ΠΎΠΏΡ‚ΠΈΠΌΠ°Π»Π½Π° структура Π½Π° изпълнСниС.

ΠžΡΠ½ΠΎΠ²Π½ΠΈΡ‚Π΅ прСдимства Π½Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° Ρ‚Π°Π±Π»ΠΈΡ‡Π½ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π² LINQ запитванията:

  1. Π’ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚Ρ‚Π°, ΠΊΠ°ΠΊΡ‚ΠΎ ΠΈ Π² случая с прСдставлСнията, Π΄Π° сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° ΠΈ ΡƒΠΊΠ°ΠΆΠ΅ ΠΊΠ°Ρ‚ΠΎ ΠΎΠ±Π΅ΠΊΡ‚, Π½ΠΎ ΠΌΠΎΠΆΠ΅ Π΄Π° сС ΠΏΡ€Π΅Π΄Π°Π΄Π΅ Π½Π°Π±ΠΎΡ€ ΠΎΡ‚ Π²Ρ…ΠΎΠ΄Π½ΠΈ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΈ:
    FROM FUNCTION(@param1, @param2 …)
    Π² ΠΊΡ€Π°ΠΉΠ½Π° смСтка ΠΌΠΎΠΆΠ΅ Π΄Π° сС постигнС гъвкаво ΠΈΠ·Π²Π»ΠΈΡ‡Π°Π½Π΅ Π½Π° Π΄Π°Π½Π½ΠΈ
  2. Π’ случай Π½Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° Ρ‚Π°Π±Π»ΠΈΡ‡Π½Π° функция няма Ρ‚Π°ΠΊΠΈΠ²Π° строги ограничСния, ΠΊΠ°ΠΊΠ²ΠΈΡ‚ΠΎ имашС с индСксируСмитС прСдставлСния, описани ΠΏΠΎ-Π³ΠΎΡ€Π΅:
    1. Π’Π°Π±Π»ΠΈΡ‡Π½ΠΈ подсказки:
      Ρ‡Ρ€Π΅Π· LINQ Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° сС посочат ΠΊΠ°ΠΊΠ²ΠΈ индСкси трябва Π΄Π° сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ ΠΈ Π΄Π° сС опрСдСля Π½ΠΈΠ²ΠΎΡ‚ΠΎ Π½Π° изолация Π½Π° Π΄Π°Π½Π½ΠΈΡ‚Π΅ ΠΏΡ€ΠΈ заявка.
      Но във функцията Ρ‚Π΅Π·ΠΈ Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΠΈ ΡΡŠΡ‰Π΅ΡΡ‚Π²ΡƒΠ²Π°Ρ‚.
      Π‘ функцията ΠΌΠΎΠΆΠ΅ Π΄Π° сС постигнС Π΄ΠΎΡΡ‚Π°Ρ‚ΡŠΡ‡Π½ΠΎ постоянСн ΠΏΠ»Π°Π½ Π·Π° изпълнСниС Π½Π° заявката, ΠΊΡŠΠ΄Π΅Ρ‚ΠΎ са ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈ ΠΏΡ€Π°Π²ΠΈΠ»Π° Π·Π° Ρ€Π°Π±ΠΎΡ‚Π° с индСкситС ΠΈ Π½ΠΈΠ²Π°Ρ‚Π° Π½Π° изолация Π½Π° Π΄Π°Π½Π½ΠΈΡ‚Π΅.
    2. Π˜Π·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° функция позволяват, Π² сравнСниС с индСксируСми прСдставлСния, Π΄Π° сС ΠΏΠΎΠ»ΡƒΡ‡ΠΈ:
      • слоТна Π»ΠΎΠ³ΠΈΠΊΠ° Π·Π° ΠΈΠ·Π²Π»ΠΈΡ‡Π°Π½Π΅ Π½Π° Π΄Π°Π½Π½ΠΈ (Π²ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»Π½ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° Ρ†ΠΈΠΊΠ»ΠΈ)
      • ΠΈΠ·Π²Π»ΠΈΡ‡Π°Π½Π΅ Π½Π° Π΄Π°Π½Π½ΠΈ ΠΎΡ‚ мноТСство Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΈ Ρ‚Π°Π±Π»ΠΈΡ†ΠΈ.
      • Π½Π°Ρ‡ΠΈΠ½ Π½Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ UNION ΠΈ EXISTS

  3. ΠŸΡ€Π΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΠ΅ OPTION Π΅ ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠΎΠ»Π΅Π·Π½ΠΎ, ΠΊΠΎΠ³Π°Ρ‚ΠΎ трябва Π΄Π° осигурим ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Π½Π° ΠΏΠ°Ρ€Π°Π»Π΅Π»ΠΈΠ·ΠΌΠ°. OPTION(MAXDOP N), Ρ€Π΅Π΄Π° Π½Π° ΠΏΠ»Π°Π½Π° Π·Π° изпълнСниС Π½Π° заявката. НапримСр:
    • ΠΌΠΎΠΆΠ΅ Π΄Π° сС ΡƒΠΊΠ°ΠΆΠ΅ ΠΏΡ€ΠΈΠ½ΡƒΠ΄ΠΈΡ‚Π΅Π»Π½ΠΎ ΠΏΡ€Π΅ΡΡŠΠ·Π΄Π°Π²Π°Π½Π΅ Π½Π° ΠΏΠ»Π°Π½Π° Π·Π° заявка. OPTION (RECOMPILE)
    • ΠΌΠΎΠΆΠ΅ Π΄Π° сС ΡƒΠΊΠ°ΠΆΠ΅ нСобходимостта ΠΎΡ‚ ΠΏΡ€ΠΈΠ½ΡƒΠ΄ΠΈΡ‚Π΅Π»Π½ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° ΠΏΠ»Π°Π½Π° Π·Π° заявка Ρ€Π΅Π΄Π° Π½Π° ΡΠ²ΡŠΡ€Π·Π²Π°Π½Π΅, посочСн Π² заявката. OPTION (FORCE ORDER)

    По-ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎ Π·Π° OPTION Π΅ описано. Ρ‚ΡƒΠΊ.

  4. Π˜Π·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° Π½Π°ΠΉ-тСсния ΠΈ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌ срСз Π½Π° Π΄Π°Π½Π½ΠΈΡ‚Π΅:
    Няма Π½ΡƒΠΆΠ΄Π° Π΄Π° сС Π΄ΡŠΡ€ΠΆΠ°Ρ‚ Π³ΠΎΠ»Π΅ΠΌΠΈ Π½Π°Π±ΠΎΡ€ΠΈ ΠΎΡ‚ Π΄Π°Π½Π½ΠΈ Π² кСшовС (ΠΊΠ°ΠΊΡ‚ΠΎ Π² случая с индСксируСмитС прСдставлСния), ΠΎΡ‚ ΠΊΠΎΠΈΡ‚ΠΎ слСд Ρ‚ΠΎΠ²Π° трябва Π΄Π° сС Ρ„ΠΈΠ»Ρ‚Ρ€ΠΈΡ€Π°Ρ‚ Π΄Π°Π½Π½ΠΈΡ‚Π΅ ΠΏΠΎ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚ΡŠΡ€.
    НапримСр, ΠΈΠΌΠ° Ρ‚Π°Π±Π»ΠΈΡ†Π°, Π·Π° която Π·Π° Ρ„ΠΈΠ»Ρ‚ΡŠΡ€ WHERE сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ Ρ‚Ρ€ΠΈ ΠΏΠΎΠ»Π΅Ρ‚Π° (a, b, c).

    Условно Π·Π° всички заявки ΠΈΠΌΠ° постоянно условиС a = 0 and b = 0..

    Π’ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‚ΠΎΠ²Π°, заявката Π·Π° ΠΏΠΎΠ»Π΅Ρ‚ΠΎ c Π΅ ΠΏΠΎ-Π²Π°Ρ€ΠΈΠ°Ρ‚ΠΈΠ²Π½Π°.

    НСка условиСто a = 0 and b = 0. дСйствитСлно Π½ΠΈ ΠΏΠΎΠΌΠ°Π³Π° Π΄Π° ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡ΠΈΠΌ нСобходимия ΠΏΠΎΠ»ΡƒΡ‡Π°Π²Π°Π½ Π½Π°Π±ΠΎΡ€ Π΄ΠΎ хиляди записи, Π½ΠΎ условиСто ΠΏΠΎ с ΡƒΠΆ суТава ΠΈΠ·Π±ΠΎΡ€Π° Π΄ΠΎ стотина записа.

    Π’ΡƒΠΊ Ρ‚Π°Π±Π»ΠΈΡ‡Π½Π°Ρ‚Π° функция ΠΌΠΎΠΆΠ΅ Π΄Π° сС ΠΎΠΊΠ°ΠΆΠ΅ ΠΏΠΎ-ΠΈΠ·Π³ΠΎΠ΄Π΅Π½ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚.

    Π‘ΡŠΡ‰ΠΎ Ρ‚Π°ΠΊΠ° Ρ‚Π°Π±Π»ΠΈΡ‡Π½Π°Ρ‚Π° функция Π΅ ΠΏΠΎ-прСдсказуСма ΠΈ постоянна ΠΏΠΎ Π²Ρ€Π΅ΠΌΠ΅ Π½Π° изпълнСниС.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ΠΈ

НСка Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π·Π° рСализация Π½Π° ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° Π½Π° Π±Π°Π·Π° Π΄Π°Π½Π½ΠΈ Questions.

Има заявка SELECT, която ΡΠ²ΡŠΡ€Π·Π²Π° няколко Ρ‚Π°Π±Π»ΠΈΡ†ΠΈ ΠΈ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Π΅Π΄Π½ΠΎ прСдставлСниС (OperativeQuestions), Π² ΠΊΠΎΠ΅Ρ‚ΠΎ сС провСрява ΠΏΠΎ email принадлСТността (Ρ‡Ρ€Π΅Π· EXISTS) към "Активни запитвания"([OperativeQuestions]):

Π—Π°ΠΏΠΈΡ‚Π²Π°Π½Π΅ β„– 1

(@p__linq__0 nvarchar(4000))SELECT
1 AS [C1],
[Extent1].[Id] AS [Id],
[Join2].[Object_Id] AS [Object_Id],
[Join2].[ObjectType_Id] AS [ObjectType_Id],
[Join2].[Name] AS [Name],
[Join2].[ExternalId] AS [ExternalId]
FROM [dbo].[Questions] AS [Extent1]
INNER JOIN (SELECT [Extent2].[Object_Id] AS [Object_Id],
[Extent2].[Question_Id] AS [Question_Id], [Extent3].[ExternalId] AS [ExternalId],
[Extent3].[ObjectType_Id] AS [ObjectType_Id], [Extent4].[Name] AS [Name]
FROM [dbo].[ObjectQuestions] AS [Extent2]
INNER JOIN [dbo].[Objects] AS [Extent3] ON [Extent2].[Object_Id] = [Extent3].[Id]
LEFT OUTER JOIN [dbo].[ObjectTypes] AS [Extent4] 
ON [Extent3].[ObjectType_Id] = [Extent4].[Id] ) AS [Join2] 
ON [Extent1].[Id] = [Join2].[Question_Id]
WHERE ([Extent1].[AnswerId] IS NULL) AND (0 = [Extent1].[Exp]) AND ( EXISTS (SELECT
1 AS [C1]
FROM [dbo].[OperativeQuestions] AS [Extent5]
WHERE (([Extent5].[Email] = @p__linq__0) OR (([Extent5].[Email] IS NULL) 
AND (@p__linq__0 IS NULL))) AND ([Extent5].[Id] = [Extent1].[Id])
));

ΠŸΡ€Π΅Π΄ΡΡ‚Π°Π²Π»Π΅Π½ΠΈΠ΅Ρ‚ΠΎ ΠΈΠΌΠ° доста слоТна структура: Π² Π½Π΅Π³ΠΎ ΠΈΠΌΠ° съСдинСния Π½Π° ΠΏΠΎΠ΄Π·Π°ΠΏΠΈΡ‚ΠΈ ΠΈ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° сортировка DISTINCT, ΠΊΠΎΠ΅Ρ‚ΠΎ Π΅ сравнитСлно рСсурсоСмка опСрация.

Π˜Π·Π²Π»ΠΈΡ‡Π°Π½Π΅ ΠΎΡ‚ OperativeQuestions Π½Π° ΠΎΠΊΠΎΠ»ΠΎ дСсСт хиляди записа.

ΠžΡΠ½ΠΎΠ²Π½ΠΈΡΡ‚ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ Π½Π° Ρ‚ΠΎΠ·ΠΈ запрос Π΅, Ρ‡Π΅ Π·Π° записитС ΠΎΡ‚ външния запрос сС изпълнява Π²ΡŠΡ‚Ρ€Π΅ΡˆΠ½ΠΎ ΠΏΠΎΠ΄Π·Π°ΠΏΠΈΡ‚Π²Π°Π½Π΅ Π²ΡŠΡ€Ρ…Ρƒ прСдставянСто [OperativeQuestions], ΠΊΠΎΠ΅Ρ‚ΠΎ трябва Π΄Π° ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡ΠΈ ΠΈΠ·Π²Π΅ΠΆΠ΄Π°Π½Π΅Ρ‚ΠΎ Π½Π° Π΄Π°Π½Π½ΠΈ Π·Π° [Email] = @p__linq__0 (Ρ‡Ρ€Π΅Π· EXISTS) Π΄ΠΎ стотици записа.

И ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π°, Ρ‡Π΅ ΠΏΠΎΠ΄Π·Π°ΠΏΠΈΡ‚Π²Π°Π½Π΅Ρ‚ΠΎ трябва Π΄Π° изчисли вСднъТ записитС Π·Π° [Email] = @p__linq__0, Π° слСд Ρ‚ΠΎΠ²Π° Ρ‚Π΅Π·ΠΈ стотина записа трябва Π΄Π° сС ΡΠ²ΡŠΡ€ΠΆΠ°Ρ‚ ΠΏΠΎ Id с Questions, ΠΈ Π·Π°ΠΏΡ€ΠΎΡΡŠΡ‚ Ρ‰Π΅ бъдС Π±ΡŠΡ€Π·.

Π’ΡΡŠΡ‰Π½ΠΎΡΡ‚ ΠΎΠ±Π°Ρ‡Π΅ сС ΠΈΠ·Π²ΡŠΡ€ΡˆΠ²Π° послСдоватСлно ΡΠ²ΡŠΡ€Π·Π²Π°Π½Π΅ Π½Π° всички Ρ‚Π°Π±Π»ΠΈΡ†ΠΈ: ΠΈ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Π½Π° ΡΡŠΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΠΈΠ΅Ρ‚ΠΎ Π½Π° Id Π½Π° Questions с Id ΠΎΡ‚ OperativeQuestions, ΠΈ Ρ„ΠΈΠ»Ρ‚Ρ€ΠΈΡ€Π°Π½Π΅ ΠΏΠΎ Email.

Π‘ΡŠΡ‰Π½ΠΎΡΡ‚Ρ‚Π° Π½Π° записа Ρ€Π°Π±ΠΎΡ‚ΠΈ с всички дСсСтки хиляди записи Π½Π° OperativeQuestions, Π° Π²ΡΡŠΡ‰Π½ΠΎΡΡ‚ са Π½ΡƒΠΆΠ½ΠΈ само интСрСсуващитС Π΄Π°Π½Π½ΠΈ ΠΏΠΎ Email.

ВСкст Π½Π° прСдставянСто OperativeQuestions:

Π—Π°ΠΏΠΈΡ‚Π²Π°Π½Π΅ β„– 2

 
CREATE VIEW [dbo].[OperativeQuestions]
AS
SELECT DISTINCT Q.Id, USR.email AS Email
FROM            [dbo].Questions AS Q INNER JOIN
                         [dbo].ProcessUserAccesses AS BPU ON BPU.ProcessId = CQ.Process_Id 
OUTER APPLY
                     (SELECT   1 AS HasNoObjects
                      WHERE   NOT EXISTS
                                    (SELECT   1
                                     FROM     [dbo].ObjectUserAccesses AS BOU
                                     WHERE   BOU.ProcessUserAccessId = BPU.[Id] AND BOU.[To] IS NULL)
) AS BO INNER JOIN
                         [dbo].Users AS USR ON USR.Id = BPU.UserId
WHERE        CQ.[Exp] = 0 AND CQ.AnswerId IS NULL AND BPU.[To] IS NULL 
AND (BO.HasNoObjects = 1 OR
              EXISTS (SELECT   1
                           FROM   [dbo].ObjectUserAccesses AS BOU INNER JOIN
                                      [dbo].ObjectQuestions AS QBO 
                                                  ON QBO.[Object_Id] =BOU.ObjectId
                               WHERE  BOU.ProcessUserAccessId = BPU.Id 
                               AND BOU.[To] IS NULL AND QBO.Question_Id = CQ.Id));

ΠŸΡŠΡ€Π²ΠΎΠ½Π°Ρ‡Π°Π»Π½ΠΎΡ‚ΠΎ ΠΌΠ°ΠΏΠΈΡ€Π°Π½Π΅ Π½Π° прСдставянСто Π² DbContext (EF Core 2)

ΠΏΡƒΠ±Π»ΠΈΡ‡Π΅Π½ клас QuestionsDbContext : DbContext
{
    \/\/...
    ΠΏΡƒΠ±Π»ΠΈΡ‡Π½ΠΎ DbQuery<OperativeQuestion> ΠžΠΏΠ΅Ρ€Π°Ρ‚ΠΈΠ²Π½ΠΈΠ’ΡŠΠΏΡ€ΠΎΡΠΈ { ΠΏΠΎΠ»ΡƒΡ‡Π°Π²Π°Π½Π΅; Π·Π°Π΄Π°Π²Π°Π½Π΅; }
    \/\/...
    Π·Π°Ρ‰ΠΈΡ‚Π΅Π½ override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Query<OperativeQuestion>().ToView("ΠžΠΏΠ΅Ρ€Π°Ρ‚ΠΈΠ²Π½ΠΈΠ’ΡŠΠΏΡ€ΠΎΡΠΈ");
    }
}

Π˜Π·Ρ…ΠΎΠ΄Π΅Π½ LINQ Π·Π°ΠΏΠΈΡ‚

var businessObjectsData = await context
    .ΠžΠΏΠ΅Ρ€Π°Ρ‚ΠΈΠ²Π½ΠΈΠ’ΡŠΠΏΡ€ΠΎΡΠΈ
    .Where(x => x.Email == Email)
    .Include(x => x.Question)
    .Select(x => x.Question)
    .SelectMany(x => x.ObjectQuestions,
                (x, bo) => Π½ΠΎΠ²
                {
                    Id = x.Id,
                    ObjectId = bo.Object.Id,
                    ObjectTypeId = bo.Object.ObjectType.Id,
                    ObjectTypeName = bo.Object.ObjectType.Name,
                    ObjectExternalId = bo.Object.ExternalId
                })
    .ToListAsync();

Π’ Ρ‚ΠΎΠ·ΠΈ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π΅Π½ случай сС Ρ€Π°Π·Π³Π»Π΅ΠΆΠ΄Π° Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅Ρ‚ΠΎ Π½Π° Ρ‚ΠΎΠ·ΠΈ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ Π±Π΅Π· инфраструктурни ΠΏΡ€ΠΎΠΌΠ΅Π½ΠΈ, Π±Π΅Π· въвСТданС Π½Π° ΠΎΡ‚Π΄Π΅Π»Π½Π° Ρ‚Π°Π±Π»ΠΈΡ†Π° с Π³ΠΎΡ‚ΠΎΠ²ΠΈ Ρ€Π΅Π·ΡƒΠ»Ρ‚Π°Ρ‚ΠΈ (β€žΠΠΊΡ‚ΠΈΠ²Π½ΠΈ Π·Π°ΠΏΠΈΡ‚Π²Π°Π½ΠΈΡβ€œ), Π·Π° която Π±ΠΈ Π±ΠΈΠ» Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΡŠΠΌ Π·Π° запълванС Π½Π° Π΄Π°Π½Π½ΠΈ ΠΈ ΠΏΠΎΠ΄Π΄ΡŠΡ€ΠΆΠ°Π½Π΅ Π½Π° актуалността ΠΉ.

Π’ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‡Π΅ Π΅ Π΄ΠΎΠ±Ρ€ΠΎ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅, ΠΈΠΌΠ° ΠΈ Π΄Ρ€ΡƒΠ³Π° Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ Π·Π° оптимизация Π½Π° Π·Π°Π΄Π°Ρ‡Π°Ρ‚Π°.

ΠžΡΠ½ΠΎΠ²Π½Π°Ρ‚Π° Ρ†Π΅Π» Π΅ Π΄Π° ΠΊΠ΅ΡˆΠΈΡ€Π°ΠΌΠ΅ записитС ΠΏΠΎ [Email] = @p__linq__0 ΠΎΡ‚ прСдставянСто ΠžΠΏΠ΅Ρ€Π°Ρ‚ΠΈΠ²Π½ΠΈΠ’ΡŠΠΏΡ€ΠΎΡΠΈ.

Π’ΡŠΠ²Π΅ΠΆΠ΄Π°ΠΌΠ΅ Ρ‚Π°Π±Π»ΠΈΡ‡Π½Π°Ρ‚Π° функция [dbo].[OperativeQuestionsUserMail] Π² Π±Π°Π·Π°Ρ‚Π° Π΄Π°Π½Π½ΠΈ.

Π˜Π·ΠΏΡ€Π°Ρ‰Π°ΠΉΠΊΠΈ Email ΠΊΠ°Ρ‚ΠΎ Π²Ρ…ΠΎΠ΄Π΅Π½ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚ΡŠΡ€, ΠΏΠΎΠ»ΡƒΡ‡Π°Π²Π°ΠΌΠ΅ ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎ Ρ‚Π°Π±Π»ΠΈΡ†Π° с Π΄Π°Π½Π½ΠΈ:

Π—Π°ΠΏΠΈΡ‚Π²Π°Π½Π΅ β„– 3


CREATE FUNCTION [dbo].[OperativeQuestionsUserMail]
(
    @Email  nvarchar(4000)
)
RETURNS
@tbl TABLE
(
    [Id]           uniqueidentifier,
    [Email]      nvarchar(4000)
)
AS
BEGIN
        INSERT INTO @tbl ([Id], [Email])
        SELECT Id, @Email
        FROM [ΠžΠΏΠ΅Ρ€Π°Ρ‚ΠΈΠ²Π½ΠΈΠ’ΡŠΠΏΡ€ΠΎΡΠΈ]  AS [x] WHERE [x].[Email] = @Email;
     
    RETURN;
END

Π’ΡƒΠΊ сС Π²Ρ€ΡŠΡ‰Π° Ρ‚Π°Π±Π»ΠΈΡ†Π° с Π΄Π°Π½Π½ΠΈ с ΠΏΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»Π½ΠΎ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π° структура.

Π—Π° Π΄Π° Π±ΡŠΠ΄Π°Ρ‚ запитванията към OperativeQuestionsUserMail ΠΎΠΏΡ‚ΠΈΠΌΠ°Π»Π½ΠΈ, с ΠΎΠΏΡ‚ΠΈΠΌΠ°Π»Π½ΠΈ ΠΏΠ»Π°Π½ΠΎΠ²Π΅ Π½Π° запитванията, Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠ° строга структура, Π° Π½Π΅ RETURNS TABLE AS RETURN…

Π’ Ρ‚ΠΎΠ·ΠΈ случай Ρ‚ΡŠΡ€ΡΠ΅Π½ΠΎΡ‚ΠΎ Π—Π°ΠΏΠΈΡ‚Π²Π°Π½Π΅ 1 сС ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ²Π° Π² Π—Π°ΠΏΠΈΡ‚Π²Π°Π½Π΅ 4:

Π—Π°ΠΏΠΈΡ‚Π²Π°Π½Π΅ β„– 4

(@p__linq__0 nvarchar(4000))SELECT
1 AS [C1],
[Extent1].[Id] AS [Id],
[Join2].[Object_Id] AS [Object_Id],
[Join2].[ObjectType_Id] AS [ObjectType_Id],
[Join2].[Name] AS [Name],
[Join2].[ExternalId] AS [ExternalId]
FROM (
    SELECT Id, Email FROM [dbo].[OperativeQuestionsUserMail] (@p__linq__0)
) AS [Extent0]
INNER JOIN [dbo].[Questions] AS [Extent1] ON([Extent0].Id=[Extent1].Id)
INNER JOIN (SELECT [Extent2].[Object_Id] AS [Object_Id], [Extent2].[Question_Id] AS [Question_Id], [Extent3].[ExternalId] AS [ExternalId], [Extent3].[ObjectType_Id] AS [ObjectType_Id], [Extent4].[Name] AS [Name]
FROM [dbo].[ObjectQuestions] AS [Extent2]
INNER JOIN [dbo].[Objects] AS [Extent3] ON [Extent2].[Object_Id] = [Extent3].[Id]
LEFT OUTER JOIN [dbo].[ObjectTypes] AS [Extent4] 
ON [Extent3].[ObjectType_Id] = [Extent4].[Id] ) AS [Join2] 
ON [Extent1].[Id] = [Join2].[Question_Id]
WHERE ([Extent1].[AnswerId] IS NULL) AND (0 = [Extent1].[Exp]);

ΠœΠ°ΠΏΠΈΡ€Π°Π½Π΅ Π½Π° прСдставлСниС ΠΈ функция Π² DbContext (EF Core 2)

ΠΏΡƒΠ±Π»ΠΈΡ‡Π΅Π½ клас QuestionsDbContext : DbContext
{
    //...
    ΠΏΡƒΠ±Π»ΠΈΡ‡Π΅Π½ DbQuery ΠžΠΏΠ΅Ρ€Π°Ρ‚ΠΈΠ²Π½ΠΈΠ’ΡŠΠΏΡ€ΠΎΡΠΈ { get; set; }
    //...
    Π·Π°Ρ‰ΠΈΡ‚Π΅Π½ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ Π½Π° void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Query().ToView("ΠžΠΏΠ΅Ρ€Π°Ρ‚ΠΈΠ²Π½ΠΈΠ’ΡŠΠΏΡ€ΠΎΡΠΈ");
    }
}

ΠΏΡƒΠ±Π»ΠΈΡ‡Π΅Π½ статичСн клас FromSqlQueries
{
    ΠΏΡƒΠ±Π»ΠΈΡ‡Π΅Π½ статичСн IQueryable GetByUserEmail(Ρ‚Π°Π·ΠΈ DbQuery ΠΈΠ·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ, Π½ΠΈΠ· Email)
        => ΠΈΠ·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ.FromSql($"SELECT Id, Email FROM [dbo].[ΠžΠΏΠ΅Ρ€Π°Ρ‚ΠΈΠ²Π½ΠΈΠ’ΡŠΠΏΡ€ΠΎΡΠΈΠŸΠΎΡ‚Ρ€Π΅Π±ΠΈΡ‚Π΅Π»ΠŸΠΎΡ‰Π°] ({Email})");
}

ΠšΡ€Π°Π΅Π½ LINQ-запрос

var businessObjectsData = await context
    .ΠžΠΏΠ΅Ρ€Π°Ρ‚ΠΈΠ²Π½ΠΈΠ’ΡŠΠΏΡ€ΠΎΡΠΈ
    .GetByUserEmail(Email)
    .Include(x => x.Π’ΡŠΠΏΡ€ΠΎΡ)
    .Select(x => x.Π’ΡŠΠΏΡ€ΠΎΡ)
    .SelectMany(x => x.ΠžΠ±Π΅ΠΊΡ‚Π’ΡŠΠΏΡ€ΠΎΡΠΈ,
                (x, bo) => new
                {
                    Id = x.Id,
                    ObjectId = bo.Object.Id,
                    ObjectTypeId = bo.Object.ObjectType.Id,
                    ObjectTypeName = bo.Object.ObjectType.Name,
                    ObjectExternalId = bo.Object.ExternalId
                })
    .ToListAsync();

Π’Ρ€Π΅ΠΌΠ΅Ρ‚ΠΎ Π·Π° изпълнСниС Π΅ намаляло ΠΎΡ‚ 200-800 мс Π½Π° 2-20 мс ΠΈ Ρ‚.Π½., Ρ‚.Π΅. дСсСтки ΠΏΡŠΡ‚ΠΈ ΠΏΠΎ-Π±ΡŠΡ€Π·ΠΎ.

Ако Π²Π·Π΅ΠΌΠ΅ΠΌ ΠΏΠΎ-ΠΎΠ±ΠΎΠ±Ρ‰Π΅Π½ΠΎ, вмСсто 350 мс ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ…ΠΌΠ΅ 8 мс.

ΠžΡ‚ ΠΎΡ‡Π΅Π²ΠΈΠ΄Π½ΠΈΡ‚Π΅ прСдимства ΠΏΠΎΠ»ΡƒΡ‡Π°Π²Π°ΠΌΠ΅:

  1. ΠΎΠ±Ρ‰ΠΎ намаляванС Π½Π° Π½Π°Ρ‚ΠΎΠ²Π°Ρ€Π²Π°Π½Π΅Ρ‚ΠΎ ΠΏΡ€ΠΈ Ρ‡Π΅Ρ‚Π΅Π½Π΅,
  2. Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»Π½ΠΎ намаляванС Π½Π° вСроятността ΠΎΡ‚ Π±Π»ΠΎΠΊΠ°ΠΆΠΈ,
  3. намаляванС Π½Π° срСдното Π²Ρ€Π΅ΠΌΠ΅ Π·Π° Π±Π»ΠΎΠΊΠ°ΠΆ Π΄ΠΎ ΠΏΡ€ΠΈΠ΅ΠΌΠ»ΠΈΠ²ΠΈ стойности.

Извод

ΠžΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΡΡ‚Π° ΠΈ Ρ„ΠΈΠ½ΠΎΡ‚ΠΎ настройванС Π½Π° заявки към Π‘Π” MS SQL Ρ‡Ρ€Π΅Π· LINQ Π΅ Π·Π°Π΄Π°Ρ‡Π°, която ΠΌΠΎΠΆΠ΅ Π΄Π° бъдС Ρ€Π΅ΡˆΠ΅Π½Π°.

Π’ Ρ‚Π°Π·ΠΈ Ρ€Π°Π±ΠΎΡ‚Π° ΠΌΠ½ΠΎΠ³ΠΎ Π²Π°ΠΆΠ½ΠΎ Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅Ρ‚ΠΎ ΠΈ послСдоватСлността.

Π’ Π½Π°Ρ‡Π°Π»ΠΎΡ‚ΠΎ Π½Π° процСса:

  1. Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π΅ Π΄Π° сС ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈ информацията, с която Ρ€Π°Π±ΠΎΡ‚ΠΈ Π·Π°ΠΏΠΈΡ‚Π²Π°Π½Π΅Ρ‚ΠΎ (стойности, ΠΈΠ·Π±Ρ€Π°Π½ΠΈ Ρ‚ΠΈΠΏΠΎΠ²Π΅ Π΄Π°Π½Π½ΠΈ),
  2. Π΄Π° сС ΠΏΡ€ΠΎΠ²Π΅Π΄Π΅ ΠΏΡ€Π°Π²ΠΈΠ»Π½ΠΎ индСксиранС Π½Π° Ρ‚Π΅Π·ΠΈ Π΄Π°Π½Π½ΠΈ,
  3. Π΄Π° сС ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈ корСктността Π½Π° ΡΠ²ΡŠΡ€Π·Π²Π°Ρ‰ΠΈΡ‚Π΅ условия ΠΌΠ΅ΠΆΠ΄Ρƒ Ρ‚Π°Π±Π»ΠΈΡ†ΠΈΡ‚Π΅.

На слСдващата итСрация Π½Π° оптимизацията сС ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΡ†ΠΈΡ€Π°Ρ‚:

  1. основата Π½Π° Π·Π°ΠΏΠΈΡ‚Π²Π°Π½Π΅Ρ‚ΠΎ ΠΈ основният Ρ„ΠΈΠ»Ρ‚ΡŠΡ€ Π½Π° Π·Π°ΠΏΠΈΡ‚Π²Π°Π½Π΅Ρ‚ΠΎ,
  2. повтарящи сС ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΈ Π±Π»ΠΎΠΊΠΎΠ²Π΅ Π½Π° Π·Π°ΠΏΠΈΡ‚Π²Π°Π½Π΅Ρ‚ΠΎ ΠΈ Π°Π½Π°Π»ΠΈΠ· Π½Π° ΠΏΡ€ΠΈΠΏΠΎΠΊΡ€ΠΈΠ²Π°Π½Π΅Ρ‚ΠΎ Π½Π° условията.
  3. Π² SSMS ΠΈΠ»ΠΈ Π΄Ρ€ΡƒΠ³ GUI Π·Π° SQL Server ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€Π° сС самият SQL-Π·Π°ΠΏΠΈΡ‚Π²Π°Π½Π΅, (ΠΈΠ·Π²Π»ΠΈΡ‡Π°Π½Π΅ Π½Π° ΠΌΠ΅ΠΆΠ΄ΠΈΠ½Π½ΠΎ Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅ Π½Π° Π΄Π°Π½Π½ΠΈ, ΠΈΠ·Π³Ρ€Π°ΠΆΠ΄Π°Π½Π΅ Π½Π° ΠΊΡ€Π°ΠΉΠ½ΠΎ Π·Π°ΠΏΠΈΡ‚Π²Π°Π½Π΅ с ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° Ρ‚ΠΎΠ²Π° Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅ (ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΈΠΌΠ° няколко))
  4. Π½Π° послСдния Π΅Ρ‚Π°ΠΏ, Π²Π·ΠΈΠΌΠ°ΠΉΠΊΠΈ Π·Π° основа ΠΊΡ€Π°ΠΉΠ½ΠΎΡ‚ΠΎ SQL-Π·Π°ΠΏΠΈΡ‚Π²Π°Π½Π΅,, сС ΠΏΡ€Π΅ΠΈΠ·Π³Ρ€Π°ΠΆΠ΄Π° структурата Π½Π° LINQ-Π·Π°ΠΏΠΈΡ‚Π²Π°Π½Π΅Ρ‚ΠΎ.

Π’ ΠΊΡ€Π°ΠΉΠ½Π° смСтка, ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΎΡ‚ΠΎ LINQ-Π·Π°ΠΏΠΈΡ‚Π²Π°Π½Π΅ трябва Π΄Π° станС ΠΏΠΎ структура ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ‡Π½ΠΎ Π½Π° ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΡ†ΠΈΡ€Π°Π½ΠΎΡ‚ΠΎ ΠΎΠΏΡ‚ΠΈΠΌΠ°Π»Π½ΠΎ SQL-Π·Π°ΠΏΠΈΡ‚Π²Π°Π½Π΅ ΠΎΡ‚ Ρ‚ΠΎΡ‡ΠΊΠ° 3.

Благодарности

ΠžΠ³Ρ€ΠΎΠΌΠ½ΠΎ благодаря Π½Π° ΠΊΠΎΠ»Π΅Π³ΠΈΡ‚Π΅ jobgemws ΠΈ alex_ozr ΠΎΡ‚ компанията Fortis Π·Π° ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π² ΠΏΠΎΠ΄Π³ΠΎΡ‚ΠΎΠ²ΠΊΠ°Ρ‚Π° Π½Π° Ρ‚ΠΎΠ·ΠΈ ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π».

Π˜Π·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com

ΠšΡƒΠΏΠ΅Ρ‚Π΅ Π½Π°Π΄Π΅ΠΆΠ΄Π΅Π½ хостинг Π·Π° сайтовС с Π·Π°Ρ‰ΠΈΡ‚Π° ΠΎΡ‚ DDoS, VPS VDS ΡΡŠΡ€Π²ΡŠΡ€ΠΈ πŸ”₯ ΠšΡƒΠΏΠ΅Ρ‚Π΅ Π½Π°Π΄Π΅ΠΆΠ΄Π΅Π½ хостинг Π·Π° сайтовС с Π·Π°Ρ‰ΠΈΡ‚Π° ΠΎΡ‚ DDoS, VPS VDS ΡΡŠΡ€Π²ΡŠΡ€ΠΈ | ProHoster