Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Kinerja MySQL dari VIEW untuk tabel yang dikombinasikan dengan UNION ALL

Saya setuju dengan semua poin dalam jawaban bagus Bill Karwin.

T: Apakah praktik normal untuk membuat tampilan untuk kueri gabungan yang dibahas dan menggunakannya di gabungan saya, subpilihan, dll?

J: Dengan MySQL, praktik yang lebih normal adalah menghindari penggunaan pernyataan "CREATE VIEW".

T: Dalam hal kinerja - apakah akan lebih buruk, sama atau lebih baik dibandingkan dengan hanya memasukkannya ke dalam gabungan, subpilihan dll?

J: Merujuk objek tampilan akan memiliki kinerja yang identik dengan tampilan inline yang setara.

(Mungkin ada sedikit lebih banyak pekerjaan untuk mencari objek tampilan, memeriksa hak istimewa, dan kemudian mengganti referensi tampilan dengan SQL yang disimpan, vs. mengirim pernyataan yang hanya sedikit lebih lama. Tapi semua itu perbedaannya tidak signifikan.)

T: Apakah ada kerugian memiliki pandangan dalam kasus ini?

J: Kelemahan terbesar adalah bagaimana MySQL memproses tampilan, apakah itu disimpan atau inline. MySQL akan selalu menjalankan kueri tampilan dan mewujudkan hasil dari kueri tersebut sebagai tabel MyISAM sementara. Tetapi tidak ada perbedaan apakah definisi tampilan disimpan, atau apakah itu disertakan sebaris. (Proses RDBMS lain terlihat jauh berbeda dari MySQL).

Satu kelemahan besar dari tampilan adalah predikat dari kueri luar TIDAK PERNAH didorong ke dalam kueri tampilan. Setiap kali Anda mereferensikan tampilan itu, bahkan dengan kueri untuk nilai id tunggal, MySQL akan menjalankan kueri tampilan dan membuat tabel MyISAM sementara (tanpa indeks di atasnya), dan MAKA MySQL akan menjalankan kueri luar terhadap sementara itu Tabel MyISAM.

Jadi, dalam hal kinerja, pikirkan referensi ke tampilan yang setara dengan "CREATE TEMPORARY TABLE t (cols) ENGINE=MyISAM " dan "INSERT INTO t (cols) SELECT ... ".

MySQL sebenarnya mengacu pada tampilan sebaris sebagai "tabel turunan", dan nama itu sangat masuk akal, ketika kita memahami apa yang dilakukan MySQL dengannya.

Preferensi pribadi saya adalah untuk tidak menggunakan pernyataan "CREATE VIEW". Kelemahan terbesar (seperti yang saya lihat) adalah bahwa ia "menyembunyikan" SQL yang sedang dieksekusi. Untuk pembaca masa depan, referensi ke tampilan terlihat seperti tabel. Dan kemudian, ketika dia menulis pernyataan SQL, dia akan merujuk tampilan seperti tabel, jadi sangat nyaman. Kemudian dia memutuskan dia akan bergabung dengan tabel itu ke dirinya sendiri, dengan referensi lain untuk itu. (Untuk referensi kedua, MySQL juga menjalankan kueri itu lagi, dan membuat tabel MyISAM sementara (dan tidak terindeks) lainnya. Dan sekarang ada operasi GABUNG pada itu. Dan kemudian predikat "WHERE view.column ='foo'" akan ditambahkan pada kueri luar.

Ini akhirnya "menyembunyikan" peningkatan kinerja yang paling jelas, menggeser predikat itu ke dalam kueri tampilan.

Dan kemudian, seseorang datang dan memutuskan mereka akan membuat tampilan baru, yang merujuk pada tampilan lama. Dia hanya membutuhkan subset baris, dan tidak dapat mengubah tampilan yang ada karena dapat merusak sesuatu, jadi dia membuat tampilan baru... CREATE VIEW myview FROM publicview p WHERE p.col ='foo'.

Dan, sekarang, referensi ke myview pertama-tama akan menjalankan kueri tampilan publik, membuat tabel MyISAM sementara, kemudian kueri myview dijalankan melawannya, membuat tabel MyISAM sementara lainnya, yang akan dilawan oleh kueri luar.

Pada dasarnya, kenyamanan tampilan berpotensi menimbulkan masalah kinerja yang tidak disengaja. Dengan definisi tampilan yang tersedia di database untuk digunakan siapa saja, seseorang akan menggunakannya, meskipun itu bukan solusi yang paling tepat.

Setidaknya dengan tampilan sebaris, orang yang menulis pernyataan SQL lebih sadar akan SQL yang sebenarnya sedang dieksekusi, dan semua SQL yang ditata memberikan kesempatan untuk mengubahnya untuk kinerja.

Dua sen saya.

MENJAMIN SQL BEASTLY

Saya menemukan bahwa menerapkan aturan pemformatan reguler (yang dilakukan alat saya secara otomatis) dapat membengkokkan SQL yang mengerikan menjadi sesuatu yang dapat saya baca dan kerjakan.

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

Saya kemungkinan besar akan menghindari tampilan sebaris sama sekali, dan menggunakan ekspresi bersyarat dalam daftar SELECT, meskipun ini menjadi lebih berat untuk banyak kolom.

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. Jalankan mysql create function statement dengan PHP

  2. Kapan MENGUNCI TABEL di MySQL (tabel MyISAM)?

  3. Mengoptimalkan ORDER BY

  4. Fungsi MySQL LEAST() – Temukan Argumen Terkecil dalam Daftar Argumen

  5. Identitas (pada pembuatan basis data) kesalahan kunci yang ditentukan terlalu panjang