سؤال

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

على سبيل المثال, النظر في هذا بسيط المخطط.شخص يعيش في العنوان و هو يعمل من قبل الشركة.كل عنوان صاحب العمل اختيارية وبالتالي يمكن أن تكون فارغة.

@Entity
public  class Person {
    public name;

    @ManyToOne
    @Column(nullable=true)
    public Address address

    @ManyToOne
    @Column(nullable=true)
    public Company employer
}

@Entity
public  class Address {
    address attributes ...
}

@Entity
public  class Company {
    company attributes ...
}

ليس هو مبين أعلاه هو أن كل JPA كيان نوعا من معرف (الرئيسية):

@Id
public Integer id;

المشكلة أراه هو أن واحدة JPA الاستعلام عن النتائج في عدة استعلامات SQL على قاعدة البيانات.على سبيل المثال التالي JPA الاستعلام:

select p from Person p where ...

النتائج في استعلام SQL:

select ... from Person where ...

وأيضا التالية زوج من استعلامات SQL كل استرجاع الشخص:

select ... from Address a where a.id=xxx
select ... from Company c where c.id=yyy

هذا له تأثير كبير على الأداء.إذا كان الاستعلام نتيجة مجموعة من 1000 شخص ، فإنه يولد 1+1000+1000=2001 استعلامات SQL.

لذلك حاولت تحسين JPA الاستعلام من خلال إجبارها على الانضمام إلى:

select p from Person p join p.address a join p.employer e where ...

أو:

select p, a, e from Person p join p.address a join p.employer e where ...

هذه النتائج في واحد استعلام SQL مع مجموعة من الصلات.المشكلة إذا كان عنوان صاحب العمل أو باطل ، ثم انضم الاستعلام لن تجد ذلك.

لذلك أنا تركت مع إما باستخدام الانضمام إلى أقل الاستعلام التي هي بطيئة أو سريعة انضم الاستعلام الذي لا استرداد الصفوف فارغة العلاقات.يجب أن يكون في عداد المفقودين على شيء هنا.بالتأكيد هناك طريقة سريعة وكاملة الاستعلام.

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

المحلول

تخميني هو أن كنت في حاجة الى اليسار الانضمام ، أي ،

SELECT p FROM Person p LEFT JOIN p.address a LEFT JOIN p.employer e WHERE...

انظر هذا بلوق الدخول على سبيل المثال

علما أنه في الواقع لم يحاكم هذا مع JPA, لكنه يعمل بشكل جيد في HQL ، الذي هو أساس JPA القياسية في العديد من الطرق.

السبب انها لا تعمل مع عادي الانضمام هو أن الافتراضي هو صلة داخلية.

نصائح أخرى

حاول تحديد batchsize (@BatchSize) على عنوان الشركة الكيانات.فإنه لن يتم تحميل لهم في الانضمام إلى (هل هذا ما كنت بعد؟), ولكن فإنه سيتم تحميل مجموعة منهم في كل مرة واحدة يتم تحميل.على batchsize يقول كم يجب تحميل عندما يكتشف أنه يحتاج واحد.

إذا كان لديك batchsize 1 (الافتراضي), تحميل 10 أشخاص.ثم أعاد عليهم ، قراءة عنوان الشركة البنود, ثم السبات سوف الاستعلام عن 10 أشخاص ، ثم في كل مرة يحتاج العنوان أو شركة واحدة من هؤلاء الناس ثم أنها سوف تجعل استعلام عن ذلك عنوان هذا الشخص.

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

إذا كان لديك عنوان الشركة مع BatchSize من 7 وأنت بالتكرار خلال 10 أشخاص ، ثم هذا سوف يؤدي إلى 5 الاستعلامات, بدلا من 21 يو سوف تحصل في هذه اللحظة.لا تزال لا 1 أن الانضمام إلى القفر تعطيك.ومع ذلك ، فإن الانضمام سيكون أبطأ في الحالات حيث كنت ترغب فقط في الشخص الأشياء لن تكون مؤثرة العنوان/الشركة الكيانات جزءا لا يتجزأ منها (أقول كنت ترغب فقط في الحصول على قائمة من الشخص معرفات ، أو كم عدد الذكور/الإناث)

إلقاء نظرة على:http://hibernate.org/hib_docs/v3/reference/en/html/performance.html

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