Memori yang Digunakan tidak dibebaskan setelah SQL BULK Insert / BCP Ekspor

10

Saya telah membuat tabel SQL yang sangat mendasar sebagai berikut

CREATE TABLE [dbo].[TickData](
[Date] [varchar](12) NULL,
[Time] [varchar](12) NOT NULL,
[Symbol] [varchar](12) NOT NULL,
[Side] [varchar](2) NOT NULL,
[Depth] [varchar](2) NOT NULL,
[Quote] [varchar](12) NOT NULL,
[Size] [varchar](18) NOT NULL
    ) ON [PRIMARY]

Saya kemudian melakukan Insert Massal 3 Gig

    BULK
    INSERT TickData
    FROM 
    'C:\SUMO.csv'
    GO

Kemudian penggunaan RAM untuk server SQL pergi Skyrocking, memakan ~ 30Go RAM:

masukkan deskripsi gambar di sini

masukkan deskripsi gambar di sini

Saya lebih suka berpikir ini adalah perilaku abnormal dan tindakan dapat diambil untuk menghindari hal ini.

EDIT:
Ok, Ini tampaknya menjadi perilaku default. Cukup adil.
Namun, mengapa memori tidak dibebaskan lama setelah Sisipan Massal selesai?

Beberapa pertimbangan ekstra:
Pada komentar tentang SQL server yang membebaskan memori ketika "disuruh" oleh OS, pengalaman langsung saya pada Server 24-Core 32 Gb Xeon membuktikan ini tidak eksak: Setelah ekstrak BCP Memory-Voracious selesai Saya memiliki kumpulan .Net Instances dari aplikasi pemrosesan data saya yang perlu memproses data yang diekstraksi, dan mereka dibiarkan tersedak / berjuang untuk berbagi memori yang tersisa untuk mencoba melakukan pekerjaan mereka, yang membutuhkan waktu lebih lama ketika SQL Server diaktifkan mati dan memori tersedia untuk semua aplikasi untuk dibagikan. Saya harus menghentikan Agen SQL Server untuk membuat semuanya berjalan lancar dan mencegah Aplikasi dari crash untuk Articiallt yang menyebabkan Pengecualian OutOfMemmroy. Adapun Pembatasan / Pembatasan Memori Brutal buatan, jika Memori Gratis tersedia, mengapa tidak menggunakannya? Idealnya ia lebih suka diatur secara dinamis untuk beradaptasi dengan apa yang tersedia daripada hanya secara paksa dibatasi "secara acak". Tapi saya kira ini adalah desain, jadi case ditutup pada poin terakhir ini.

Mehdi LAMRANI
sumber
6
Mengapa SQL Server membebaskan memori? Jika perlu memori untuk melakukan operasi ini sekali, itu akan membutuhkannya lagi. Jika SQL Server merilis memori, untuk apa Anda menggunakannya? Mengapa memori harus bebas? Jika Anda menggunakan memori untuk hal lain, maka insert massal ini berjalan lagi, apa yang harus terjadi?
Aaron Bertrand
Satu-satunya tindakan yang dapat Anda lakukan untuk menghindari hal ini adalah mengatur ukuran memori maksimal. Untuk "memulihkan" memori, Anda dapat memulai kembali layanan SQL Server. Jelas, itu akan melepaskan memori, dan ketika layanan restart itu akan mengalokasikan memori secara normal.
TMN
Saya membersihkan edit terakhir. Jika Anda ingin memiliki argumen / diskusi tentang kelebihan atau masalah tentang bagaimana SQL Server (atau mesin DB lainnya) dikodekan, temukan tempat yang lebih baik untuk melakukannya. Pertanyaan awal telah dijawab, tampaknya benar dan cukup. Jika Q ini terus merangkak, mungkin terkunci.
JNK
Tidak ada yang salah dengan keinginan untuk mengetahui jawaban dan mendiskusikan metodologi, hanya saja tidak ada di sini di situs tanya jawab. Anda pasti dapat melakukan diskusi ini di chat atau forum di suatu tempat, tetapi Stack Exchange sedikit lebih terstruktur dan diskusi-y pertanyaan akan ditutup dengan sangat cepat.
JNK
3
Juga, sebagai non moderator, saya bertanya-tanya mengapa Anda menjalankan hal-hal non-SQL di server Anda? Kotak harus disediakan hanya untuk SQL Server, ini seperti DBA 101. Mesin itu tidak dirancang untuk lingkungan sumber daya bersama.
JNK

Jawaban:

12

Ini adalah perilaku normal untuk SQL Server untuk mengalokasikan memori sebanyak mungkin ke kolam penyangga itu. Database berfungsi dengan baik dengan banyak buffer. Jika Anda ingin mengubah perilaku, Anda dapat mengatur pengaturan 'memori server maks' . Beberapa bacaan latar belakang yang bagus tentang itu ada di sini.

Matt Whitfield
sumber
1
Sehubungan dengan hasil edit Anda, komentar Aaron adalah yang baik. Alasannya adalah bahwa tidak ada gunanya server database membebaskan memori. SQL Server akan merespons tekanan memori dan melepaskan memori jika memang harus, tetapi sebenarnya itu tidak perlu.
Matt Whitfield
@MikaJacobi Maaf, tetapi edit kedua Anda salah. Dari pola pikir pengembang, saya mengerti sudut pandang Anda, tetapi ada perbedaan antara membangun banyak aplikasi yang hidup berdampingan dan layanan server yang benar-benar harus menjadi satu-satunya layanan yang menghabiskan memori pada mesin. Jika Anda ingin SQL Server berperilaku seperti aplikasi "normal", kemudian atur memori maks dan berjalan pergi. Pertanyaan Anda adalah mengapa ia bekerja seperti ini, dan itu sudah dijawab. Jika pertanyaan Anda sekarang "baik saya tidak suka itu bekerja seperti itu" - maaf, tapi itu bukan pertanyaan lagi.
Aaron Bertrand
Cukup adil. Pandangan saya hanyalah bahwa harus ada opsi untuk mengaktifkan atau menonaktifkan ini, dan asumsi bahwa server SQL adalah satu-satunya Aplikasi pada Server benar-benar kasar (mungkin benar untuk perusahaan besar dengan jaringan besar tetapi itu bukan satu-satunya mungkin atau pengaturan yang paling umum)
Mehdi LAMRANI
Saya masih tidak mengerti mengapa Anda perlu SQL Server untuk membebaskan memori. Jika aplikasi lain akan membutuhkannya, mereka akan mengambilnya kembali dari SQL Server, dan SQL Server akan mematuhinya. Sampai aplikasi-aplikasi lain itu membutuhkannya, apa tujuan membebaskan memori melayani?
Aaron Bertrand
1
@ AaronBertrand Ok Saya mungkin salah tetapi seperti yang dinyatakan dalam edit terakhir saya yang baru, ini bukan yang saya saksikan: Memori tidak dibebaskan ketika aplikasi lain sangat membutuhkannya, menyebabkan kehancuran Memori (Karena ketidakpuasan saya ...) Bagaimanapun, mari tutup subjeknya, saya kira tidak perlu berdebat lebih dari itu.
Mehdi LAMRANI
7

Jika Anda benar-benar ingin OS mengambil kembali memori dari SQL Server, ambil file besar 20 GB dan salin melalui jaringan. SQL Server akan melepaskan memori sesuai kebutuhan OS. Tetapi saya akan menonton berbagai penghitung kinerja saat ini sedang berlangsung, dan melihat bagaimana kinerja BULK INSERT Anda berubah jika Anda menjalankannya lagi baik ketika salinan sedang berlangsung atau segera setelah itu.

Jika Anda ingin melakukan ini secara manual, maka Anda harus menetapkan batas yang lebih rendah pada pengaturan memori server maks SQL Server, dan restart layanan. Sekarang SQL Server tidak akan menggunakan 28GB bahkan jika dibutuhkan. Tapi ini tampaknya membatasi SQL Server secara artifisial.

Apa yang tampaknya Anda harapkan adalah perilaku yang lebih fleksibel, di mana Anda dapat memiliki sebagian memori bebas. Untuk tujuan apa? Apakah ini seperti menyusutkan file database untuk membebaskan ruang disk yang tidak dapat Anda gunakan untuk keperluan lain karena file database akan tumbuh lagi?

Itu lucu, jika Anda mengetik pencarian Google untuk "mengapa tidak SQL Server" penyelesaian otomatis yang paling umum adalah "lepaskan memori."

Aaron Bertrand
sumber
"Apa yang kamu harapkan adalah perilaku yang lebih fleksibel." Persis. Saya ingin SQL server untuk menggunakan semua memori yang tersedia ketika tersedia, tetapi ketika saat-saat yang berat ini berakhir, untuk kembali ke keadaan "tidur" dan membiarkan aplikasi lain yang membutuhkan memori melakukan tugasnya dengan nyaman (Anda dapat melihat pada saya edit terakhir baru pada titik ini)
Mehdi LAMRANI
Untuk kasus nyata yang menggambarkan mengapa saya perlu melakukan ini, Anda dapat melihat @ komentar terakhir saya ke JNK di bagian bawah pertanyaan
Mehdi LAMRANI
4

Sayangnya ini karena desain, silakan merujuk posting ini. Namun, dalam posting ini ia memberi Anda beberapa petunjuk tentang cara mengendalikannya.

/server/251832/sql-server-bulk-insert-physical-memory-issue

Edit Alokasi Memori

Memori tidak freednaik karena banyak mengalokasikan memori seperti aplikasi .NET. Karena alokasi memori mahal, ia akan mempertahankan alokasi itu kecuali jika OS memintanya. Tapi, jangan takut, jika OS menginginkan memori itu akan mendapatkannya, sama seperti di aplikasi NET.

Mike Perrenoud
sumber
@MikaJacobi Tentu, tidak masalah. Satu hal lagi yang perlu diperhatikan, supaya Anda tahu, SQL Server akan mengambil alih semua core juga jadi pastikan Anda membatasi jumlah core yang tersedia. Saya telah melihat SQL Server benar-benar menghancurkan sistem operasi yang dijalankan sebelumnya dan saya harus mem-boot ulang pusat data SQL Server.
Senang mendengarnya. Saya memiliki 24 Cores jadi ini tidak masalah untuk saat ini. Tetapi mengapa memori tidak dibebaskan setelah Sisipan Massal selesai?
Selama insert massal telah selesai, jika OS membutuhkan memori itu akan diberikan kepadanya, tetapi ia mengalokasikan memori sangat mirip dengan aplikasi .NET sehingga jika diperlukan dan tidak ada orang lain yang dapat mengaksesnya dengan lebih cepat.
Pengalaman hads-on saya bertentangan dengan ini (lihat edit terakhir).
Mehdi LAMRANI