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

Percepat Pembaruan MySQL/Sisipkan Pernyataan

Ada banyak masalah kinerja di sini jika Anda perlu melakukannya jutaan kali.

  • Anda sedang mempersiapkan pernyataan SQL yang sama berulang-ulang, jutaan kali. Akan lebih baik jika mempersiapkannya sekali dan mengeksekusinya jutaan kali.

  • Anda memutuskan sambungan dari database pada setiap panggilan fungsi setelah satu kueri. Itu berarti Anda perlu menghubungkan kembali setiap kali dan informasi yang disimpan dalam cache akan dibuang. Jangan lakukan itu, biarkan tetap terhubung.

  • Anda melakukan setelah setiap baris. Ini akan memperlambat segalanya. Sebagai gantinya, lakukan setelah melakukan batch.

  • Select + update atau insert mungkin bisa dilakukan sebagai upsert tunggal.

  • Bahwa Anda memasukkan begitu banyak ke dalam tabel sementara mungkin merupakan masalah kinerja.

  • Jika tabel memiliki terlalu banyak indeks yang dapat memperlambat penyisipan. Terkadang yang terbaik adalah menghapus indeks, melakukan pembaruan massal, dan membuatnya kembali.

  • Karena Anda memasukkan nilai langsung ke SQL, SQL Anda terbuka untuk serangan injeksi SQL .

Sebaliknya...

  • Gunakan pernyataan yang telah disiapkan dan ikat parameter
  • Biarkan database tetap terhubung
  • Lakukan pembaruan secara massal
  • Hanya komit di akhir rangkaian pembaruan
  • Lakukan semua perhitungan di UPDATE daripada SELECT + math + UPDATE .
  • Gunakan "UPSERT" sebagai ganti SELECT lalu UPDATE atau INSERT

Pertama, pernyataan yang disiapkan. Ini memungkinkan MySQL mengkompilasi pernyataan sekali dan kemudian menggunakannya kembali. Idenya adalah Anda menulis pernyataan dengan placeholder untuk nilai.

select id, position, impressions, clicks, ctr
from temp
where profile_id=%s and
      keyword=%s and 
      landing_page=%s

Kemudian Anda mengeksekusinya dengan nilai sebagai argumen, bukan sebagai bagian dari string.

self.cursor.execute(
   'select id, position, impressions, clicks, ctr from temp where profile_id=%s and keyword=%s and landing_page=%s',
   (profile_id, keyword, landing_page)
)

Hal ini memungkinkan database untuk men-cache pernyataan yang telah disiapkan dan tidak perlu mengkompilasi ulang setiap kali. Itu juga menghindari serangan injeksi SQL di mana penyerang pintar dapat membuat nilai yang sebenarnya lebih SQL seperti " MORE SQL HERE " . Ini adalah lubang keamanan yang sangat, sangat, sangat umum.

Catatan, Anda mungkin perlu menggunakan milik MySQL Pustaka basis data Python untuk mendapatkan pernyataan yang disiapkan dengan benar . Jangan terlalu khawatir, menggunakan pernyataan yang sudah disiapkan bukanlah masalah kinerja terbesar Anda.

Selanjutnya, yang pada dasarnya Anda lakukan adalah menambahkan ke baris yang sudah ada, atau jika tidak ada baris yang ada, menyisipkan yang baru. Ini dapat dilakukan lebih efisien dalam satu pernyataan dengan UPSERT , gabungan INSERT dan UPDATE . MySQL memilikinya sebagai INSERT ... ON DUPLICATE KEY UPDATE .

Untuk melihat bagaimana ini dilakukan, kita dapat menulis SELECT then UPDATE sebagai satu UPDATE . Perhitungan dilakukan dalam SQL.

    update temp
    set impressions = impressions + %s,
        clicks = clicks + %s,
        ctr = (ctr + %s / 2)
    where profile_id=%s and
          keyword=%s and
          landing_page=%s

INSERT Anda tetap sama...

    insert into temp
        (profile_id, landing_page, keyword, position, impressions, clicks, ctr)
        values (%s, %s, %s, %s, %s, %s, %s)

Gabungkan keduanya menjadi satu INSERT ON DUPLICATE KEY UPDATE.

    insert into temp
        (profile_id, landing_page, keyword, position, impressions, clicks, ctr)
        values (%s, %s, %s, %s, %s, %s, %s)
    on duplicate key update
    update temp
    set impressions = impressions + %s,
        clicks = clicks + %s,
        ctr = (ctr + %s / 2)

Ini tergantung pada apa kunci tabel didefinisikan sebagai. Jika Anda memiliki unique( profile_id, landing_page, keyword ) maka itu harus bekerja sama dengan kode Anda.

Bahkan jika Anda tidak dapat melakukan upsert, Anda dapat menghilangkan SELECT dengan mencoba UPDATE , memeriksa apakah itu memperbarui sesuatu, dan jika tidak melakukan INSERT .

Lakukan pembaruan secara massal. Alih-alih memanggil subrutin yang melakukan satu pembaruan dan komit, berikan daftar besar hal-hal yang akan diperbarui dan kerjakan dalam satu lingkaran. Anda bahkan dapat memanfaatkan executemany untuk menjalankan pernyataan yang sama dengan beberapa nilai. Kemudian komit.

Anda mungkin dapat melakukan UPSERT dalam jumlah besar. INSERT dapat mengambil beberapa baris sekaligus. Misalnya, ini menyisipkan tiga baris.

insert into whatever
    (foo, bar, baz)
values (1, 2, 3),
       (4, 5, 6), 
       (7, 8, 9)

Anda mungkin dapat melakukan hal yang sama dengan INSERT ON DUPLICATE KEY UPDATE Anda mengurangi jumlah overhead untuk berbicara dengan database. Lihat postingan ini untuk contoh (di PHP, tapi Anda harus bisa beradaptasi).

Pengorbanan ini mengembalikan ID dari baris yang disisipkan terakhir, tetapi itu adalah jedanya.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cara menggunakan Hibernate eqOrIsNull()

  2. Di Django, bagaimana cara memilih 100 catatan acak dari database?

  3. Opsi ORM terbaik dari ASP.NET MVC ke mySQL

  4. Bagaimana membandingkan hanya tanggal dan tahun di php codeigniter

  5. Bagaimana cara mengirim elemen HTML melalui JSON menggunakan PHP?