سؤال

في MySQL 5.0.75-0ubuntu10.2 لقد حصلت على تخطيط جدول ثابت من هذا القبيل:

وparent الجدول مع معرف parent2 جدول مع معرف الجدول children1 مع parentId

CREATE TABLE  `Parent` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(200) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB
CREATE TABLE  `Parent2` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(200) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB
CREATE TABLE  `Children1` (
  `id` int(11) NOT NULL auto_increment,
  `parentId` int(11) NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `parent` (`parentId`)
) ENGINE=InnoDB

وللأطفال يحتوي على الأصل في أحد الجداول Parent أو Parent2. عندما كنت في حاجة للحصول على أطفال يمكنني استخدام استعلام مثل ما يلي:

select * from Children1 c 
inner join (
select id as parentId from Parent
union 
select id as parentId from Parent2
) p on p.parentId = c.parentId

شرح هذه العوائد الاستعلام:

+----+--------------+------------+-------+---------------+---------+---------+------+------+-----------------------------------------------------+
| id | select_type  | table      | type  | possible_keys | key     | key_len | ref  | rows | Extra                                               |
+----+--------------+------------+-------+---------------+---------+---------+------+------+-----------------------------------------------------+
|  1 | PRIMARY      | NULL       | NULL  | NULL          | NULL    | NULL    | NULL | NULL | Impossible WHERE noticed after reading const tables | 
|  2 | DERIVED      | Parent     | index | NULL          | PRIMARY | 4       | NULL |    1 | Using index                                         | 
|  3 | UNION        | Parent2    | index | NULL          | PRIMARY | 4       | NULL |    1 | Using index                                         | 
| NULL | UNION RESULT | <union2,3> | ALL   | NULL          | NULL    | NULL    | NULL | NULL |                                                     | 
+----+--------------+------------+-------+---------------+---------+---------+------+------+-----------------------------------------------------+
4 rows in set (0.00 sec)

والذي هو معقول نظرا للتخطيط.

والآن المشكلة: الاستعلام السابق لا طائل منه إلى حد ما، لأنه إرجاع أية أعمدة من العناصر الأم. في لحظة وإضافة المزيد من الأعمدة إلى الاستعلام الداخلي سيتم استخدام أي مؤشر بعد الآن:

mysql> explain select * from Children1 c  inner join ( select id as parentId,name from Parent union  select id as parentId,name from Parent2 ) p on p.parentId = c.parentId;
+----+--------------+------------+------+---------------+------+---------+------+------+-----------------------------------------------------+
| id | select_type  | table      | type | possible_keys | key  | key_len | ref  | rows | Extra                                               |
+----+--------------+------------+------+---------------+------+---------+------+------+-----------------------------------------------------+
|  1 | PRIMARY      | NULL       | NULL | NULL          | NULL | NULL    | NULL | NULL | Impossible WHERE noticed after reading const tables | 
|  2 | DERIVED      | Parent     | ALL  | NULL          | NULL | NULL    | NULL |    1 |                                                     | 
|  3 | UNION        | Parent2    | ALL  | NULL          | NULL | NULL    | NULL |    1 |                                                     | 
| NULL | UNION RESULT | <union2,3> | ALL  | NULL          | NULL | NULL    | NULL | NULL |                                                     | 
+----+--------------+------------+------+---------------+------+---------+------+------+-----------------------------------------------------+
4 rows in set (0.00 sec)

ويمكن لأي شخص أن يفسر لماذا لم يتم استخدام (PRIMARY) مؤشرات أي أكثر من ذلك؟ هل هناك حلا لهذه المشكلة إذا ممكن دون الحاجة إلى تغيير تخطيط DB؟

وشكرا!

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

المحلول

وأعتقد أن محسن تسقط بمجرد البدء في سحب عدة أعمدة في الاستعلام المستمدة بسبب احتمال أنه سيحتاج لتحويل أنواع البيانات في الاتحاد (وليس في هذه الحالة، ولكن بصفة عامة). قد يكون أيضا بسبب حقيقة أن الاستعلام الخاص بك يريد أساسا أن يكون فرعي المستمدة المترابطة، وهو أمر غير ممكن (من <لأ href = "http://dev.mysql.com/doc/refman/5.0/en/ لم يذكر اسمه-views.html "يختلط =" نوفولو noreferrer "> dev.mysql.com ):

<اقتباس فقرة>   

والاستعلامات الفرعية في الاستعلامات الفرعية عبارة FROM لا يمكن ربط، ما لم تستخدم في غضون شرط ON من JOIN العملية.

وما يحاولون القيام به (ولكن غير صالح) هو:

select * from Children1 c 
inner join (
select id as parentId from Parent where Parent.id = c.parentId
union 
select id as parentId from Parent2 where Parent.id = c.parentId
) p 

Result: "Unknown column 'c.parentId' in 'where clause'.

هل هناك سبب كنت لا تفضل اثنين من اليسار ينضم وIFNULLs:

select *, IFNULL(p1.name, p2.name) AS name from Children1 c
left join Parent p1 ON p1.id = c.parentId
left join Parent2 p2 ON p2.id = c.parentId

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

(select * from Children1 c join Parent p1 ON p1.id = c.parentId)
union
(select * from Children1 c join Parent2 p2 ON p2.id = c.parentId)

نصائح أخرى

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

وسوف نوصي أيضا قراءة هذه الوثائق والتي ترى وبت ذات الصلة MYSQL :: الأمثل استعلامات مع شرح

وهذه المادة يمكن أن تكون مفيدة أيضا 7 طرق لإقناع الخلية لاستخدام الفهرس حق

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