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

Dukungan JSON asli di MYSQL 5.7 :apa pro dan kontra dari tipe data JSON di MYSQL?

SELECT * FROM t1
WHERE JSON_EXTRACT(data,"$.series") IN ...

Menggunakan kolom di dalam ekspresi atau fungsi seperti ini merusak peluang kueri menggunakan indeks untuk membantu mengoptimalkan kueri. Kueri yang ditampilkan di atas dipaksa untuk melakukan pemindaian tabel.

Klaim tentang "akses yang efisien" menyesatkan. Artinya, setelah kueri memeriksa baris dengan dokumen JSON, ia dapat mengekstrak bidang tanpa harus mengurai teks sintaks JSON. Tetapi masih membutuhkan pemindaian tabel untuk mencari baris. Dengan kata lain, kueri harus memeriksa setiap baris.

Dengan analogi, jika saya sedang mencari buku telepon untuk orang-orang dengan nama depan "Bill", saya masih harus membaca setiap halaman di buku telepon, bahkan jika nama depan telah disorot untuk membuatnya sedikit lebih cepat untuk menemukannya.

MySQL 5.7 memungkinkan Anda untuk menentukan kolom virtual dalam tabel, dan kemudian membuat indeks pada kolom virtual.

ALTER TABLE t1
  ADD COLUMN series AS (JSON_EXTRACT(data, '$.series')),
  ADD INDEX (series);

Kemudian jika Anda menanyakan kolom virtual, itu dapat menggunakan indeks dan menghindari pemindaian tabel.

SELECT * FROM t1
WHERE series IN ...

Ini bagus, tapi agak meleset dari penggunaan JSON. Bagian menarik dari penggunaan JSON adalah memungkinkan Anda untuk menambahkan atribut baru tanpa harus melakukan ALTER TABLE. Tapi ternyata Anda harus menentukan kolom tambahan (virtual), jika Anda ingin mencari bidang JSON dengan bantuan indeks.

Tetapi Anda tidak perlu mendefinisikan kolom dan indeks virtual untuk setiap dalam dokumen JSON—hanya yang ingin Anda telusuri atau urutkan. Mungkin ada atribut lain di JSON yang hanya perlu Anda ekstrak di daftar pilih seperti berikut:

SELECT JSON_EXTRACT(data, '$.series') AS series FROM t1
WHERE <other conditions>

Saya biasanya akan mengatakan bahwa ini adalah cara terbaik untuk menggunakan JSON di MySQL. Hanya di daftar pilihan.

Saat Anda mereferensikan kolom di klausa lain (JOIN, WHERE, GROUP BY, HAVING, ORDER BY), akan lebih efisien menggunakan kolom konvensional, bukan kolom dalam dokumen JSON.

Saya menyajikan ceramah yang disebut Cara Menggunakan JSON di MySQL Salah di konferensi Percona Live pada bulan April 2018. Saya akan memperbarui dan mengulangi pembicaraan di Oracle Code One pada musim gugur.

Ada masalah lain dengan JSON. Misalnya, dalam pengujian saya, diperlukan ruang penyimpanan 2-3 kali lebih banyak untuk dokumen JSON dibandingkan dengan kolom konvensional yang menyimpan data yang sama.

MySQL mempromosikan kemampuan JSON baru mereka secara agresif, sebagian besar untuk mencegah orang bermigrasi ke MongoDB. Tetapi penyimpanan data berorientasi dokumen seperti MongoDB pada dasarnya adalah cara pengorganisasian data yang non-relasional. Berbeda dengan relasional. Saya tidak mengatakan yang satu lebih baik dari yang lain, itu hanya teknik yang berbeda, cocok untuk berbagai jenis kueri.

Anda harus memilih untuk menggunakan JSON saat JSON membuat kueri Anda lebih efisien.

Jangan memilih teknologi hanya karena baru, atau demi mode.

Sunting:Implementasi kolom virtual di MySQL seharusnya menggunakan indeks jika klausa WHERE Anda menggunakan ekspresi yang persis sama dengan definisi kolom virtual. Artinya, harus berikut ini gunakan indeks pada kolom virtual, karena kolom virtual didefinisikan AS (JSON_EXTRACT(data,"$.series"))

SELECT * FROM t1
WHERE JSON_EXTRACT(data,"$.series") IN ...

Kecuali saya telah menemukan dengan menguji fitur ini bahwa itu TIDAK berfungsi karena alasan tertentu jika ekspresinya adalah fungsi ekstraksi JSON. Ini berfungsi untuk jenis ekspresi lain, hanya saja bukan fungsi JSON. PEMBARUAN:ini dilaporkan berhasil, akhirnya, di MySQL 5.7.33.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Kesalahan:pilih perintah ditolak untuk pengguna '<userid>'@'<ip-address>' untuk tabel '<table-name>'

  2. Cara paling efisien untuk mendapatkan jumlah baris tabel

  3. Tidak dapat mengembalikan hasil dari prosedur tersimpan menggunakan kursor Python

  4. perbarui nilai kolom dengan kolom tabel lain berdasarkan kondisi

  5. Masukkan ke dalam tabel MySQL atau perbarui jika ada