كيف يمكنني استمرار البيانات إلى القرص، وكلاهما تحديثه عشوائيا، ويتفقه مرة أخرى بكفاءة إلى ذاكرة الوصول العشوائي؟

StackOverflow https://stackoverflow.com/questions/1274562

سؤال

أحتاج إلى تخزين ما يصل إلى عشرات أو حتى مئات الملايين من قطع البيانات على القرص. تحتوي كل قطعة من البيانات على معلومات مثل:

id=23425
browser=firefox
ip-address=10.1.1.1
outcome=1.0

يمكن إضافة أجزاء جديدة من البيانات بمعدل ما يصل إلى 1 لكل مللي ثانية.

لذلك مجموعة بسيطة نسبيا من أزواج القيمة الرئيسية، حيث يمكن أن تكون القيم سلاسل أو أعداد صحيحة أو يطفو. في بعض الأحيان، قد أحتاج إلى تحديث قطعة البيانات مع معرف معين، وتغيير حقل العلم من 0 إلى 1. بمعنى آخر، أحتاج إلى أن أكون قادرا على القيام بإجراء عمليات بحث أساسية عشوائية عن طريق المعرف، وتعديل البيانات (في الواقع فقط العائمة نقطة "النتيجة" مجال - لذلك لن أحتاج أبدا لتعديل حجم القيمة).

الشرط الآخر هو أنني بحاجة إلى أن أكون قادرا على دفق هذه البيانات خارج القرص (النظام غير مهم بشكل خاص) بكفاءة. هذا يعني أن رأس القرص الصلب لا ينبغي أن يحتاج إلى القفز حول القرص لقراءة البيانات، بل يجب أن يقرأ في كتل القرص المتتالية.

أنا أكتب هذا في جافا.

لقد فكرت في استخدام قاعدة بيانات مضمنة، ولكن DB4O ليست خيارا كما هو GPL وبقية التعليمات البرمجية ليست كذلك. أنا قلق أيضا من كفاءة استخدام قاعدة بيانات SQL المضمنة، مع إعطاء العلامة العامة للترجمة من وإلى استعلامات SQL.

هل لدى أي شخص أي أفكار؟ قد يتعين علي بناء حل مخصص لهذا (حيث أنا أتعامل مباشرة مع bytebuffers، ومعالجة بحث الهوية)؟

هل كانت مفيدة؟

المحلول 7

في النهاية قررت تسجيل البيانات إلى القرص كما يأتي، والحفاظ عليه أيضا في الذاكرة حيث يمكنني تحديثه. بعد فترة من الوقت، أكتب البيانات إلى القرص وحذف السجل.

نصائح أخرى

ماذا عن H2.ب ال رخصة يجب أن تعمل من أجلك.

  • يمكنك استخدام H2 مجانا. يمكنك دمجه في طلبك (بما في ذلك التطبيقات التجارية)، ويمكنك توزيعها.
  • الملفات التي تحتوي على التعليمات البرمجية فقط غير مشمولة بهذا الترخيص (إنها "صديقة تجارية").
  • يجب نشر التعديلات على التعليمات البرمجية المصدر H2.
  • لا تحتاج إلى توفير شفرة المصدر في H2 إذا لم تقم بتعديل أي شيء.

انا حصلت

1000000 إدراج في 22492ms (44460.252534234394 صف / ثانية)

100000 تحديثات في 9565ms (10454.783063251438 الصف / ثانية)

من عند

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Random;


/**
 * @author clint
 *
 */
public class H2Test {

  static int testrounds = 1000000;

  public static void main(String[] args) {
    try {
      Class.forName("org.h2.Driver");

    Connection conn = DriverManager.
        getConnection("jdbc:h2:/tmp/test.h2", "sa", "");
    // add application code here
    conn.createStatement().execute("DROP TABLE IF EXISTS TEST");
    conn.createStatement().execute("CREATE TABLE IF NOT EXISTS TEST(id INT PRIMARY KEY, browser VARCHAR(64),ip varchar(16), outcome real)"); 
    //conn.createStatement().execute("CREATE INDEX IDXall ON TEST(id,browser,ip,outcome");


    PreparedStatement ps = conn.prepareStatement("insert into TEST (id, browser, ip, outcome) values (?,?,?,?)");
    long time = System.currentTimeMillis();
    for ( int i = 0; i < testrounds; i++ ) {
      ps.setInt(1,i);
      ps.setString(2,"firefox");
      ps.setString(3,"000.000.000.000");
      ps.setFloat(4,0);
      ps.execute();
    }
    long last = System.currentTimeMillis() ;
    System.out.println( testrounds + " insert in " + (last - time) + "ms (" + ((testrounds)/((last - time)/1000d)) + " row/sec)" );

    ps.close();
    ps = conn.prepareStatement("update TEST set outcome = 1 where id=?");
    Random random = new Random();
    time = System.currentTimeMillis();

    /// randomly updadte 10% of the entries
    for ( int i = 0; i < testrounds/10; i++ ) {
      ps.setInt(1,random.nextInt(testrounds));
      ps.execute();
    }

    last = System.currentTimeMillis();
    System.out.println( (testrounds/10) + " updates in " + (last - time) + "ms (" + ((testrounds/10)/((last - time)/1000d)) + " row/sec)" );

    conn.close();

    } catch (ClassNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (SQLException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }

}

JDBM هي قاعدة بيانات مدمجة رائعة ل Java (وليس مرهونة مع الترخيص كإصدار Java من Berkley). سيكون يستحق المحاولة. إذا لم تكن بحاجة إلى ضمانات حمض (أي أنك على ما يرام مع وقوع قاعدة البيانات معطلان في حالة حدوث تعطل)، فقم بإيقاف تشغيل مدير المعاملات (يزيد السرعة بشكل كبير).

أعتقد أن لديك المزيد من النجاح في كتابة شيء يخفف من أحدث السجلات النشطة في الذاكرة وتغيير بيانات قوائم الانتظار كإدراج أولوية منخفضة في DB.

أنا أفهم أن هناك زيادة طفيفة في IO باستخدام هذه الطريقة ولكن إذا كنت تتحدث عن ملايين السجلات، أعتقد أنه ستظل أسرع لأن أي خوارزمية بحثية تقوم بإنشائها ستفوقها بشكل كبير بواسطة محرك قاعدة بيانات كاملة من AA.

بامكانك ان تحاول بيركلي ديسيبل التي هي الآن مملوكة من قبل أوراكل. لديهم مصادر مفتوحة والتراخيص التجارية. يستخدم نموذج مفتاح / قيمة (مع خيار لإنشاء فهارس إذا كانت هناك حاجة إلى أشكال أخرى من الاستعلامات). هناك نسخة جافا نقية وإصدار أصلي مع ربط جافا.

http://www.zentus.com/sqlitejdbc/

قاعدة بيانات SQLite (المجال العام)، موصل JDBC مع رخصة BSD، مواطن عن مجموعة كاملة من المنصات (OSX، Linux، Windows)، مضاهاة الباقي.

يمكنك استخدام Derby Apache (أو Javadb) التي يتم تجميعها مع JDK. ومع ذلك، إذا لم تقدم DBMS السرعة المطلوبة، فقد تقوم بتنفيذ هيكل ملف معين بنفسك. إذا كان هناك حاجة إلى بحث مفتاح دقيق فقط، فقد تستخدم ملف Hash لتنفيذه. يعد ملف Hash-file أسرع بنية ملف لمثل هذه المتطلبات (أسرع بكثير من هياكل ملفات الأغراض العامة مثل الأشجار والشبكات B التي يتم استخدامها في DBS). كما يوفر كفاءة تدفق مقبولة.

هل ألقيت نظرة على قاعدة بيانات أوراكل "Timesten"؟ لها DB في الذاكرة التي من المفترض أن تكون عالية الأداء. لا تعرف ما هي التكاليف / التراخيص، إلخ، ولكن إلقاء نظرة على موقع Oracles والبحث عنها. يجب أن يكون تنزيل Eval متاحا.

أود أيضا أن نلقي نظرة لمعرفة ما إذا كان هناك أي شيء موجود بناء على EHCACHE أو JCS قد يساعد.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top