أولاً ، يتم تقديم ثلاثة طرق برمجة إدخال دفعة JDBC لمقارنتها. المحتوى المحدد كما يلي
يستخدم إدخال دفعة JDBC بشكل أساسي لاستيراد البيانات وتسجيلها لأن السجلات مكتوبة بشكل عام في الملف أولاً.
لقد استخدمت برنامج تشغيل JDBC لـ MySQL 5.1.5 لاختبار ثلاث طرق أكثر شيوعًا
الطريقة 1: استخدم reparedStatement لإضافة دفعات
حاول {class.forname ("com.mysql.jdbc.driver") ؛ conn = drivermanager.getConnection (o_url ، اسم المستخدم ، كلمة المرور) ؛ conn.setautocommit (false) ؛ String sql = "insert adlogs (IP ، موقع الويب ، yyyymmdd ، ساعة ، object_id) القيم (؟ ،؟ ،؟ ،؟)" ؛ PreparedStatement perst = conn.preparestatement (sql ، resultset.type_scroll_sevisitive ، resultset.concur_read_only) ؛ لـ (int x = 0 ؛ x <size ؛ x ++) {prest.SetString (1 ، "192.168.1.1") ؛ Prest.SetString (2 ، "LocalHost") ؛ Prest.SetString (3 ، "20081009") ؛ prest.setint (4 ، 8) ؛ Prest.SetString (5 ، "11111111") ؛ prest.addbatch () ؛ } prest.executeBatch () ؛ conn.Commit () ؛ conn.close () ؛ } catch (sqlexception ex) {logger.getLogger (mylogger.class.getName ()). log (level.severe ، null ، ex) ؛ } catch (classNotFoundException ex) {logger.getLogger (mylogger.class.getName ()). log (level.severe ، null ، ex) ؛ } اشرح معنى المعلمتين التاليتين عند إنشاء بيان:
المعلمة الأولى تحدد نوع ResultSet. الخيارات هي:
type_forward_only: النوع الافتراضي. لا يُسمح بالوصول إلى الأمام إلا مرة واحدة ولن يتأثر بالتغييرات التي أجراها المستخدمون الآخرون في قاعدة البيانات.
type_scroll_insensitive: يسمح بحركة للأمام أو للخلف في القائمة ، وحتى تحديد موقع محدد ، مثل الانتقال إلى السجل الرابع في القائمة أو نقل سجلين للخلف من الموضع الحالي. لن تتأثر بالتغييرات التي أجراها المستخدمون الآخرون في قاعدة البيانات.
type_scroll_sevinitive: مثل type_scroll_insintivity ، يُسمح بالمواقع في السجلات. يتأثر هذا النوع بالتغييرات التي أجراها المستخدمون الآخرون. إذا قام المستخدم بحذف سجل بعد تنفيذ الاستعلام ، فسيختفي هذا السجل من مجموعة النتائج. وبالمثل ، سوف تنعكس التغييرات في قيم البيانات في ResultSet.
تحدد المعلمة الثانية تزامن مجموعة النتائج ، والتي تحدد ما إذا كان يمكن تحديث مجموعة النتائج. الخيارات هي:
concur_read_only: هذه هي القيمة الافتراضية ، المحددة أنه لا يمكن تحديثها
resultset concur_updatable: يحدد أنه يمكن تحديث مجموعة النتائج
الطريقة 2: استخدام بيان لإضافة طريقة الدُفعات
conn.setautocommit (false) ؛ stmt stmt = conn.createStatement (resultset.type_scroll_sensitive ، resultset.concur_read_only) ؛ لـ (int x = 0 ؛ x <size ؛ x ++) {stmt.addbatch ("insert في adlogs (IP ، موقع ويب ، yyyymmdd ، ساعة ، كائن_) ('192.168.1.3' ، 'localhost' ، '20081009' ، 8 ، '23123')") ؛ } stmt.executeBatch () ؛ conn.Commit () ؛الطريقة 3: استخدم البيان مباشرة
conn.setautocommit (false) ؛ stmt stmt = conn.createStatement (resultset.type_scroll_sensitive ، resultset.concur_read_only) ؛ لـ (int x = 0 ؛ x <size ؛ x ++) {stmt.execute ("insert في adlogs (IP ، موقع ويب ، yyyymdd ، ساعة ، كائن_) ('192.168.1.3' ، 'localhost' ، '20081009' ، 8 ، '23123')") ؛ } conn.Commit () ؛ متوسط وقت الاختبار لإدخال 100000 قطعة من البيانات باستخدام الطريقة أعلاه هو:
الطريقة 1: 17.844S
الطريقة 2: 18.421s
الطريقة 3: 16.359s
يمكن ملاحظة أن إدخال عبارات دفعة JDBC لا يحسن الأداء فحسب ، بل هو أبطأ من عدم استخدام دفعة. بالطبع ، قد يكون هذا مرتبطًا بطريقة تنفيذ برامج تشغيل JDBC المحددة. المرفق هو رمز الاختبار الخاص بي ، والذي يمكن استخدامه لتشغيله على جهاز الكمبيوتر الخاص بي.
عند إجراء إدخال دفعة ، فإن الشيء الأكثر أهمية هو إلغاء التقديم تلقائيًا ، لذلك لا ينبغي أن يهم ما إذا كان يتم استخدام بناء جملة الدُفعات JDBC أم لا.
conn.setautocommit (خطأ)
أنا شخصياً أعتقد أن الطريقة الأولى هي الأكثر ملاءمة وعملية.
مثال شرح لبيانات إدخال دفعة JDBC :
في الآونة الأخيرة ، عندما كنت أعمل على برنامج لاستيراد بيانات Excel إلى قاعدة بيانات ، كنت أستعد لاستخدام إدخال دفعة JDBC بسبب كمية البيانات الكبيرة. لذلك يتم استخدام التحضير. addbatch () ؛ عند إضافة قطع 1W من البيانات ، يتم تنفيذ عملية الإدراج ، يتم استخدام reparedStatement.executeBatch (). اعتقدت أن هذا سيكون سريعًا ، لكن الأمر استغرق مني أكثر من 30 دقيقة لإدراج 65،536 قطعة من البيانات ، والتي كانت تتجاوز توقعاتي تمامًا. لذلك سألت زملائي كيف قاموا بمعالجة هذا النوع من استيراد البيانات على نطاق واسع. لقد وجدت أنهم استخدموا أيضًا معالجة إدخال دفعة JDBC ، ولكن على عكسي ، استخدموا consetautocommit (false) ؛ ثم أعدت. لذلك حاولت مرة أخرى ، ما هي المعجزة؟ استغرق الأمر نصف ساعة فقط لاستيراد هذه البيانات ، وبعد إضافة هاتين الجملتين ، استغرق الأمر 15 ثانية فقط لإكمالها. لذلك راجعت السبب ووجدت التفسير التالي عبر الإنترنت:
* عند استيراد البيانات إلى innodb ، تأكد من أن MySQL لا يتم تمكين وضع الالتزام التلقائي لأن ذلك
يتطلب تدفق السجل إلى القرص لكل إدراج. لتعطيل الالتزام التلقائي أثناء عملية الاستيراد الخاصة بك ، تحيط به
قم بتعيين بيانات الالتزام التلقائي:
تعيين AutoCommit = 0 ؛
... بيانات استيراد SQL ...
يقترف؛
في المرة الأولى ، يكون ذلك على وجه التحديد لأنه لا يوجد setautocommit (خطأ) ؛ لكل عبارة إدراج ، سيتم إنشاء سجل إلى القرص. لذلك ، على الرغم من تعيين إدراج الدُفعات ، فإن تأثيره يشبه إدراج واحد ، مما يؤدي إلى إدخال بطيء للغاية.
بعض الرموز هي كما يلي:
String sql = "insert in table *****" ؛ consetautocommit (false) ؛ ps = con.preparestatement (sql) ؛ for (int i = 1 ؛ i <65536 ؛ i ++) {ps.addbatch () ؛ // insert 1W سجلات مرة واحدة إذا (i ٪ 10000 == 0) {ps.executeBatch () ؛ con.Commit () ؛ }} // إدراج أقل من 1W بيانات ps.executeBatch () ؛ con.Commit () ؛ما سبق هو مجرد طبق جانبي ، ثم "الخدمة" يتبعها:
1. اختبار بيانات كتابة الدُفعات
بدء طويل = system.currentTimeMillis () ؛ daorecord daorecord = new daorecord () ؛ قائمة <T> list = new ArrayList <T> () ؛ لـ (int i = 1 ؛ i <= 1000 ؛ i ++) {for (int j = 1 ؛ j <= 1000 ؛ j ++) {t t = new t () ؛ T.Seti (i) ؛ T.SetJ (J) ؛ list.add (t) ؛ }} daorecord.insertBatch (قائمة) ؛ System.out.println ("الاستهلاك الوقت:" + (System.CurrentTimeMillis ()-START) + "MS") ؛ 2. اختبار بيانات كتابة الدُفعات
public void insertbatch (list <t> list) {string sql = "insert in t (go ، back) (؟ ،؟)" ؛ dbhelper dbh = new dbhelper (sql) ؛ connect conn = dbh.ReturnConn () ؛ جرب {conn.setautocommit (false) ؛ // لاحظ أن هذه الجملة يجب أن تكون خاطئة ، راجع المرجع الأول preparedStatement ps = conn.preparestatement (sql) ؛ لـ (int i = 0 ؛ i <list.size () ؛ i ++) {ps.setInt (1 ، list.get (i) .geti ()) ؛ ps.SetInt (2 ، list.get (i) .getj ()) ؛ Ps.AddBatch () ؛ if (i ٪ 10000 == 0) {ps.ExecuteBatch () ؛ conn.Commit () ؛ }} ps.executeBatch () ؛ conn.Commit () ؛ conn.close () ؛ } catch (sqlexception e) {// todo تم إنشاء كتلة catch e.printstacktrace () ؛ }}جدول البيانات:
النتائج التجريبية:
ما سبق هو كل شيء عن هذا المقال ، آمل أن يكون مفيدًا لتعلم الجميع.