Mysql
 sql >> база данни >  >> RDS >> Mysql

MySQL производителност на VIEW за таблици, комбинирана с UNION ALL

Съгласен съм с всички точки в отличния отговор на Бил Карвин.

В: Нормална практика ли е да създавам изглед за обсъждана заявка за съюз и да го използвам в моите присъединявания, подселекции и т.н.?

А: С MySQL по-нормалните практики са да избягвате използването на израза "CREATE VIEW".

В: По отношение на производителността - ще бъде ли по-лошо, равно или по-добро в сравнение с простото вмъкване в обединения, подселекции и т.н.?

А: Препращането към обект на изглед ще има идентична производителност като еквивалентен вграден изглед.

(Може да има малко повече работа за търсене на обекта за преглед, проверка на привилегиите и след това замяна на препратката за изглед със съхранения SQL, в сравнение с изпращането на изявление, което е малко по-дълго. Но всяко от тези разликите са незначителни.)

В: Има ли някакви недостатъци да имате изглед в този случай?

А: Най-големият недостатък е в това как MySQL обработва изглед, независимо дали е съхранен или вграден. MySQL винаги ще изпълнява заявката за изглед и ще материализира резултатите от тази заявка като временна MyISAM таблица. Но там няма разлика дали дефиницията на изглед се съхранява, или дали е включена inline. (Други RDBMS обработват изгледите много по-различно от MySQL).

Един голям недостатък на изгледа е, че предикатите от външната заявка НИКОГА не се избутват надолу в заявката за изглед. Всеки път, когато препратите този изглед, дори със заявка за една стойност на идентификатор, MySQL ще изпълни заявката за изглед и ще създаде временна MyISAM таблица (без индекси в нея), а СЛЕД MySQL ще изпълни външната заявка срещу тази временна MyISAM таблица.

Така че, по отношение на производителността, помислете за препратка към изглед наравно с „CREATE TEMPORARY TABLE t (cols) ENGINE=MyISAM " и "INSERT INTO t (cols) SELECT ... ".

MySQL всъщност се отнася до вграден изглед като „извлечена таблица“ и това име има много смисъл, когато разберем какво прави MySQL с него.

Моето лично предпочитание е да не използвам израза "CREATE VIEW". Най-големият недостатък (както го виждам) е, че "скрива" SQL, който се изпълнява. За бъдещия читател препратката към изгледа изглежда като таблица. И тогава, когато отиде да напише SQL изявление, той ще се позовава на изгледа, сякаш е таблица, толкова удобно. Тогава той решава, че ще присъедини тази маса към себе си, с друга препратка към нея. (За втората справка MySQL също изпълнява тази заявка отново и създава още една временна (и неиндексирана) таблица MyISAM. И сега има операция JOIN върху това. И тогава се добавя предикат "WHERE view.column ='foo'" на външната заявка.

В крайна сметка „скрива“ най-очевидното подобрение на производителността, плъзгайки този предикат в заявката за изглед.

И тогава някой идва и решава, че ще създаде нов изглед, който препраща към стария изглед. Той се нуждае само от подмножество от редове и не може да промени съществуващия изглед, защото това може да наруши нещо, така че той създава нов изглед... СЪЗДАВАНЕ НА ИЗГЛЕД myview ОТ publicview p WHERE p.col ='foo'.

И сега препратката към myview първо ще изпълни заявката за publicview, ще създаде временна MyISAM таблица, след което заявката myview ще се стартира спрямо нея, създавайки друга временна таблица MyISAM, срещу която ще се изпълнява външната заявка.

По принцип удобството на изгледа има потенциал за неволни проблеми с производителността. С дефиницията на изглед, налична в базата данни, която всеки може да използва, някой ще я използва, дори когато това не е най-подходящото решение.

Поне с вграден изглед, човекът, който пише SQL израза, е по-наясно с действителния SQL, който се изпълнява, и разполагането с целия този SQL дава възможност за настройването му за производителност.

Моите два цента.

УКРОТЯВАНЕ НА BEASTLY SQL

Намирам, че прилагането на редовни правила за форматиране (които моите инструменти правят автоматично) може да огъне чудовищния SQL в нещо, с което мога да чета и да работя.

SELECT row.col1
     , row.col2
     , person.*
  FROM some_table row
  LEFT
  JOIN ( SELECT 'person'  AS `person_type`
              , p.id      AS `id`
              , CONCAT(p.first_name,' ',p.surname) AS `name`
           FROM person p
          UNION ALL
         SELECT 'company' AS `person_type`
              , c.id      AS `id`
              , c.name    AS `name`
           FROM company c
       ) person
    ON person.id = row.person_id
   AND person.person_type = row.person_type

Еднакво вероятно бих избегнал вградения изглед изобщо и бих използвал условни изрази в списъка SELECT, въпреки че това става по-тромаво за много колони.

SELECT row.col1
     , row.col2
     , row.person_type AS ref_person_type
     , row.person_id   AS ref_person_id
     , CASE
       WHEN row.person_type = 'person'  THEN p.id 
       WHEN row.person_type = 'company' THEN c.id
       END AS `person_id`
     , CASE
       WHEN row.person_type = 'person'  THEN CONCAT(p.first_name,' ',p.surname)
       WHEN row.person_type = 'company' THEN c.name
       END AS `name`
  FROM some_table row
  LEFT
  JOIN person p
    ON row.person_type = 'person'
   AND p.id = row.person_id
  LEFT
  JOIN company c
    ON row.person_type = 'company'
   AND c.id = row.person_id


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Може ли някой да ми помогне да разбера значението на това съобщение за грешка в php?

  2. Кога да ЗАКЛЮЧАВАТЕ ТАБЛИЦИ в MySQL (MyISAM таблици)?

  3. Как да покажете второ падащо меню въз основа на предишна стойност на падащото меню с помощта на Javascript

  4. Стойност по подразбиране СЕГА от две колони на MySQL ГРЕШКА 1067

  5. MySQL съответстващи символи на Unicode с ascii версия