لماذا الخلية تتجاهل مفتاح "واضح" لاستخدامها في هذا بسيط انضمام الاستعلام؟
-
03-07-2019 - |
سؤال
ولدي ما كان يعتقد أن يكون استعلام بسيط، لكنه يأخذ "إلى الأبد". أنا لست كبيرة مع تحسينات SQL، حتى ظننت أنني يمكن أن تسأل يا رفاق.
إليك الاستعلام، مع شرح:
EXPLAIN SELECT *
FROM `firms_firmphonenumber`
INNER JOIN `firms_location` ON (
`firms_firmphonenumber`.`location_id` = `firms_location`.`id`
)
ORDER BY
`firms_location`.`name_en` ASC,
`firms_firmphonenumber`.`location_id` ASC LIMIT 100;
والنتيجة:
id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra
1, 'SIMPLE', 'firms_location', 'ALL', 'PRIMARY', '', '', '', 73030, 'Using temporary; Using filesort'
1, 'SIMPLE', 'firms_firmphonenumber', 'ref', 'firms_firmphonenumber_firm_id', 'firms_firmphonenumber_firm_id', '4', 'citiadmin.firms_location.id', 1, ''
ومفاتيح على firms_location:
Keyname Type Unique Packed Field Cardinality
PRIMARY BTREE Yes No id 65818
firms_location_name_en BTREE No No name_en 65818
ومفاتيح على firms_firmphonenumber:
Keyname Type Unique Packed Field Cardinality
PRIMARY BTREE Yes No id 85088
firms_firmphonenumber_firm_id BTREE No No location_id 85088
ويبدو (بالنسبة لي) أن الخلية يرفض استخدام المفتاح الأساسي للجدول firms_location ل- ولكن ليس لدي أي فكرة عن السبب
وأي مساعدة ستكون <م> كثير م> تقدير.
تحرير بعد حل نشرت
ومع الأمر تغير حسب:
EXPLAIN SELECT *
FROM `firms_firmphonenumber`
INNER JOIN `firms_location` ON (
`firms_firmphonenumber`.`location_id` = `firms_location`.`id`
)
ORDER BY
`firms_location`.`name_en` ASC,
`firms_location`.id ASC LIMIT 100;
#`firms_firmphonenumber`.`location_id` ASC LIMIT 100;
والنتيجة:
"id","select_type","table","type","possible_keys","key","key_len","ref","rows","Extra"
1,"SIMPLE","firms_location","index","PRIMARY","firms_location_name_en","767","",100,""
1,"SIMPLE","firms_firmphonenumber","ref","firms_firmphonenumber_firm_id","firms_firmphonenumber_firm_id","4","citiadmin.firms_location.id",1,""
لماذا انها قررت استخدام هذه الآن؟ الخلية يجعل بعض الخيارات ونيف ... وأي فكرة تساعد مرة أخرى:)
تحرير مع التفاصيل من جانغو
وكتبت، وكان لي هذه (مختصر) نماذج:
class Location(models.Model):
id = models.AutoField(primary_key=True)
name_en = models.CharField(max_length=255, db_index=True)
class Meta:
ordering = ("name_en", "id")
class FirmPhoneNumber(models.Model):
location = models.ForeignKey(Location, db_index=True)
number = PhoneNumberField(db_index=True)
class Meta:
ordering = ("location", "number")
وتغيير الحقل Meta.ordering فئة Locaion في ل("name_en", )
الثابتة الاستعلام ليست لديها ترتيب زائفة من قبل.
المحلول
وهذه الأمور تميل إلى أن تكون عن طريق التجربة والخطأ، ولكن حاول طلب في firms_location.id بدلا من firms_firmphonenumber.location_id. وهي نفس القيمة، ولكن قد الخلية ثم تلتقط على المؤشر.
نصائح أخرى
ومن استخدامه، للانضمام. هذا هو قيمة 'citiadmin.firms_location.id'
في العمود ref
. ومن لا تظهر في possible_keys
وkey
لأن لديك أي جملة WHERE وانها تعكس فقط مفاتيح المتوفرة لديها لجملة ORDER BY.
إذا كنت ترغب في تسريع الاستعلام الخاص بك، في محاولة فهرسة name_en
.
ولأن هناك حيث لا، ولأن أصل من حقل الصلة أعلى من من الحقل الانضمام، انها حساب أنه قد كذلك الحصول على كل شيء. وباستخدام مؤشر على الانضمام ليس السرعة التي تصل، حتى انها اللجوء إلى التحسين أقل من استخدام مؤشر للفرز.
أولا، يمكنك أن تفعل USE لإجبارها على استخدام الفهرس الذي تحدده. أيضا، حاول القيام والأمثل للتأكد من يقدر أصل صحيح. (انا التخمين كنت تستخدم INNO، الذي يقدر في سلسلة من "الغطس" عشوائية؛. إذا كان هذا هو MYISAM، الذي لا يعرف الواقع، ثم أتساءل لماذا تبدو العلاقة الأساسية كما هو الحال)
ولا تهتم فهرسة اسم أو الخ MySQL سيتم استخدام مؤشر واحد فقط لكل جدول في الانضمام، من أي وقت مضى، وسوف مؤشر الاعظم فقط عنه.
ومقدار البيانات؟ إلا إذا كان بعض الصفوف، فإن معظم قواعد البيانات يفعل مسح الجدول بغض النظر عن الأرقام القياسية لديك