PHP, YII2 dan pembentukan file excel besar

Mulai


Satu sistem akuntansi dan pelaporan yang didukung oleh perusahaan kami mulai tumbuh sangat cepat dalam jumlah data yang disimpan. Sistem ini ditulis dalam PHP menggunakan kerangka kerja Yii2. Awalnya, laporan dibuat melalui pustaka PhpSpreadsheet, yang menggantikan PhpExcel yang sudah lama ditinggalkan.

Di antara berbagai jenis pelaporan, ada satu yang sangat besar - pada kenyataannya, set lengkap semua data yang disimpan dalam database harus diunggah ke satu tabel excel. Pada tahap awal, tidak ada masalah, tetapi ketika volume mulai melebihi ratusan ribu catatan, skrip pembongkaran formasi mulai jatuh pada batas waktu habis. Untuk memulainya, kami menaikkan batas ini dan mulai mencari cara untuk menyelesaikan masalah. Tetapi solusi sementara tidak bertahan lama - masalah dengan batas waktu berubah menjadi masalah dengan batas memori. Mereka melemparkan "RAM" ke server dan menghapus memory_limit untuk operasi khusus ini. Segera, pengguna mulai mengeluh tentang kesalahan runtime lagi. Saya harus menghapus batas waktu untuk laporan lengkap. Tapi duduk dan menonton selusin menit di layar dengan indikator memuat tidak terlalu menyenangkan. Selain itu, kadang-kadang diperlukan laporan "di sini dan sekarang", dan setiap menit yang dihabiskan untuk pembentukannya ternyata sangat kritis. Eksperimen dengan pengaturan lingkungan dihentikan, menggaruk bagian belakang kepala dan mulai mengoptimalkan kode.

Cari solusinya


Hal pertama yang dilakukan adalah bahwa skrip pelaporan ditempatkan di proses latar belakang, dan pengguna memantau kemajuan melalui "bilah kemajuan". Eksekusi pekerjaan latar belakang diimplementasikan melalui mekanisme antrian menggunakan Redis untuk penyimpanan. Bekerja dalam sistem tidak berhenti, Anda dapat melakukan tugas-tugas lain dan secara berkala kembali ke halaman laporan untuk melihat apakah file sudah siap. Segera setelah file terbentuk, pengguna ditawari tautan unduhan. Tapi, seperti yang disebutkan di atas, kadang-kadang file itu diperlukan "segera", dan peningkatan kegunaan tidak menyelesaikan masalah ini. Sementara itu, jumlah data terus bertambah dan waktu yang dibutuhkan untuk membangun file mencapai 79 menit! Ini sepenuhnya tidak dapat diterima, terutama mengingat bahwa pelaporan adalah salah satu dasar dari fungsionalitas sistem ini. Tidak, semua bagian lainnya bekerja seperti jarum jam, tetapi lalat di salep ini merusak kesan keseluruhan.

Hasil pertama


Kami duduk lagi untuk analisis kode. Hal pertama yang diuji adalah proses pemilihan data dari database. Tetapi kueri telah dioptimalkan dengan cara semaksimal mungkin. Meskipun permintaan terlama adalah sampel yang mengerikan dengan lima atau enam panggilan ke FIAS mengerikan, itu berhasil dalam 2-5 detik. Titik lemah bukan dia, tetapi pembentukan file "exelnik". Upaya telah mulai mengoptimalkan proses ini. Mulai dari caching di redis, hingga penyimpangan, seperti pembentukan "excel" kecil yang terpisah di stream paralel, diikuti dengan menempelkan ke satu file. Tetapi hasilnya selalu sama: masalah dari waktu ke waktu berubah menjadi masalah dengan memori dan sebaliknya. Tidak ada jalan tengah, hanya mengalir dari satu ekstrem ke yang lain. Setelah sejumlah data, konsumsi sumber daya perpustakaan mulai tumbuh secara eksponensial dan tidak mungkin untuk mengalahkannya. PhpSpreadsheet - tidak cocok untuk file besar. Akibatnya, diputuskan untuk mengubah perpustakaan. Sebagai pilihan - menulis analog Anda sendiri untuk pembentukan file-file ex.

Analisis dan pemilihan alat


Mereka tidak terburu-buru menulis sepeda, tetapi untuk memulainya, mereka menganalisis solusi yang ada. Dari opsi yang memungkinkan, hanya kotak / semburan yang menarik. Menulis ulang modul dengan cepat menggunakan perpustakaan ini. Hasilnya, laporan lengkap diperoleh dalam 145 detik. Biarkan saya mengingatkan Anda bahwa tes terbaru dengan PhpSpreadsheet adalah 79 menit, dan di sini 2,5 menit! Pengujian yang dilakukan: menambah jumlah data sebanyak 2 kali. Laporan dihasilkan dalam 172 detik. Perbedaannya luar biasa. Tentu saja, perpustakaan tidak memiliki semua fungsi yang sama dengan PhpSpreadsheet, tetapi dalam hal ini seperangkat alat minimum sudah cukup, karena kecepatan sangat penting.

Ekstensi untuk Yii2


Keputusan akhir dibingkai sebagai perpanjangan untuk Yii2. Mungkin seseorang akan berguna. Ekstensi ini memungkinkan Anda untuk mengunggah dataset apa pun dari GridView untuk unggul sambil mempertahankan pemfilteran dan penyortiran. Ini menggunakan yii / antrian dan kotak / semburan sebagai dependensi. Masuk akal untuk menggunakan ekstensi untuk membentuk file yang sangat besar, yah, setidaknya 50.000 baris =) Saat ini, modul, yang telah menjadi dasar untuk ekstensi, terkenal menangani dengan beban hampir 600.000 baris.

Tautan ke github: Ekstensi Yii2 ExcelReport

Terima kasih atas perhatian anda!

Source: https://habr.com/ru/post/id420393/


All Articles