بديل مقابل المفتاح الطبيعي:أرقام صعبة على اختلافات الأداء؟

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

سؤال

هناك نقاش صحي بين المفاتيح البديلة والطبيعية:

مشاركة SO 1

مشاركة SO 2

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

مثال على الطريقتين، بدءاً بجدول الشركة:

1:مفتاح بديل:يحتوي الجدول على حقل معرف وهو PK (والهوية).يجب أن تكون أسماء الشركات فريدة حسب الولاية، لذلك يوجد قيد فريد هناك.

2:المفتاح الطبيعي:يستخدم الجدول اسم الشركة والحالة باعتبارهما PK - يفي بكل من PK والتفرد.

لنفترض أن شركة PK مستخدمة في 10 جداول أخرى.فرضيتي، مع عدم وجود أرقام تدعمها، هي أن النهج الرئيسي البديل سيكون أسرع بكثير هنا.

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

هل رأى أحد مقالا يقارن اختلافات الأداء على مجموعة من الجداول التي تستخدم مفاتيح بديلة ضد. نفس مجموعة الجداول باستخدام مفاتيح طبيعية؟إن البحث في SO وGoogle لم يسفر عن أي شيء جدير بالاهتمام، فقط الكثير من صياغة النظريات.


تحديث مهم:لقد بدأت في بناء أ مجموعة من جداول الاختبار التي تجيب على هذا السؤال.تبدو هكذا:

  • Partnatural - جدول الأجزاء الذي يستخدم العدد الفريد من نوعه كـ PK
  • Partsurgate - جدول الأجزاء الذي يستخدم معرف (int ، الهوية) كـ PK وله فهرس فريد على العدد
  • المصنع - معرف (كثافة العمليات، الهوية) كـ PK
  • مهندس - معرف (كثافة العمليات، الهوية) كما PK

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

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

المحلول

استخدم الأثنين!تمنع المفاتيح الطبيعية تلف قاعدة البيانات (قد يكون عدم الاتساق كلمة أفضل).عندما يكون أداء المفتاح الطبيعي "الصحيح" (لإزالة الصفوف المكررة) سيئًا بسبب الطول أو عدد الأعمدة المعنية، لأغراض الأداء، يمكن إضافة مفتاح بديل أيضًا لاستخدامه كمفاتيح خارجية في جداول أخرى بدلاً من المفتاح الطبيعي...ولكن يجب أن يظل المفتاح الطبيعي كمفتاح بديل أو فهرس فريد لمنع تلف البيانات وفرض اتساق قاعدة البيانات...

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

نصائح أخرى

تختلف المفاتيح الطبيعية عن المفاتيح البديلة في القيمة وليس النوع.

يمكن استخدام أي نوع لمفتاح بديل، مثل VARCHAR للنظام المولد slug أو أي شيء آخر.

ومع ذلك، فإن الأنواع الأكثر استخدامًا للمفاتيح البديلة هي INTEGER و RAW(16) (أو أي نوع الخاص بك RDBMS يستخدم ل GUID'س)،

مقارنة الأعداد الصحيحة البديلة والأعداد الصحيحة الطبيعية (مثل SSN) يستغرق نفس الوقت بالضبط.

مقارنة VARCHARيجب أخذ الترتيب في الاعتبار، وهي بشكل عام أطول من الأعداد الصحيحة، مما يجعلها أقل كفاءة.

مقارنة مجموعة من اثنين INTEGER ربما يكون أيضًا أقل كفاءة من مقارنة واحدة INTEGER.

في أنواع البيانات الصغيرة الحجم، من المحتمل أن يكون هذا الاختلاف النسب المئوية من النسب المئوية من الوقت اللازم لجلب الصفحات، واجتياز الفهارس، والحصول على مزالج قاعدة البيانات وما إلى ذلك.

وهنا الأرقام (في MySQL):

CREATE TABLE aint (id INT NOT NULL PRIMARY KEY, value VARCHAR(100));
CREATE TABLE adouble (id1 INT NOT NULL, id2 INT NOT NULL, value VARCHAR(100), PRIMARY KEY (id1, id2));
CREATE TABLE bint (id INT NOT NULL PRIMARY KEY, aid INT NOT NULL);
CREATE TABLE bdouble (id INT NOT NULL PRIMARY KEY, aid1 INT NOT NULL, aid2 INT NOT NULL);

INSERT
INTO    aint
SELECT  id, RPAD('', FLOOR(RAND(20090804) * 100), '*')
FROM    t_source;

INSERT
INTO    bint
SELECT  id, id
FROM    aint;

INSERT
INTO    adouble
SELECT  id, id, value
FROM    aint;

INSERT
INTO    bdouble
SELECT  id, id, id
FROM    aint;

SELECT  SUM(LENGTH(value))
FROM    bint b
JOIN    aint a
ON      a.id = b.aid;

SELECT  SUM(LENGTH(value))
FROM    bdouble b
JOIN    adouble a
ON      (a.id1, a.id2) = (b.aid1, b.aid2);

t_source هو مجرد طاولة وهمية مع 1,000,000 صفوف.

aint و adouble, bint و bdouble تحتوي على نفس البيانات بالضبط، باستثناء ذلك aint لديه عدد صحيح مثل أ PRIMARY KEY, ، بينما adouble لديه زوج من الأعداد الصحيحة المتطابقة.

على جهازي، يتم تشغيل كلا الاستعلامين لمدة 14.5 ثانية، +/- 0.1 ثانية

فرق الأداء، إن وجد، يقع ضمن نطاق التقلبات.

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