简体   繁体   English

设置MySQL外键和索引-迁移到InnoDB

[英]Setting up MySQL foreign keys and indexes - Migrating to InnoDB

I need help setting up foreign keys for migrating to InnoDB. 我需要设置外键以迁移到InnoDB的帮助。 The situation is that I have 3 tables: jobs, customers and contacts. 情况是我有3个表:工作,客户和联系人。

A job belongs to a Customer and a job belongs to a Contact. 作业属于客户,而作业属于联系人。 A Customer has many jobs and has many contacts. 客户有很多工作并且有很多联系人。 A contact belongs to a Customer and has many Jobs. 联系人属于客户,并且有很多工作。 I need help setting up foreign keys in the jobs table so that only Contacts that belong to a selected Customer can be inserted. 我需要在作业表中设置外键的帮助,以便只能插入属于所选客户的联系人。 (ie If Customer A has contacts A1 and A2 and Customer B has contact B1, once you select Customer A as the customer for a job, it will reject entries for Contact other than A1 or A2). (即,如果客户A具有联系人A1和A2,而客户B具有联系人B1,则一旦您选择客户A作为工作客户,它将拒绝A1或A2以外的联系人条目)。 Is this possible to do with foreign keys or will I have to do the verification in the programming language of my choice? 这可能与外键有关吗?还是我必须使用自己选择的编程语言来进行验证?

Here's my schema: 这是我的架构:

CREATE TABLE jobs(
  job_id INT(11) NOT NULL AUTO_INCREMENT,
  customer_id INT(11) DEFAULT NULL,
  contact_id INT(11) DEFAULT NULL,
  job_number INT(11) UNSIGNED NOT NULL DEFAULT 0,
  status_void TINYINT(1) DEFAULT 0,
  PRIMARY KEY (job_id),
  INDEX active_jobs (job_number, status_void),
  INDEX customer_id (customer_id),
  UNIQUE INDEX job_number (job_number),
  CONSTRAINT FK_jobs_contacts_contact_id FOREIGN KEY (contact_id)
  REFERENCES contacts (contact_id) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT FK_jobs_customers_customer_id FOREIGN KEY (customer_id)
  REFERENCES customers (customer_id) ON DELETE SET NULL ON UPDATE CASCADE
)
ENGINE = INNODB
CHARACTER SET utf8
COLLATE utf8_general_ci;`

CREATE TABLE customers(
  customer_id INT(11) NOT NULL AUTO_INCREMENT,
  inactive TINYINT(1) DEFAULT 0,
  customer_name VARCHAR(50) NOT NULL DEFAULT '',
  PRIMARY KEY (customer_id),
  UNIQUE INDEX customer_name (customer_name),
  INDEX inactive (inactive)
)
ENGINE = INNODB
CHARACTER SET utf8
COLLATE utf8_general_ci;

CREATE TABLE contacts(
  contact_id INT(11) NOT NULL AUTO_INCREMENT,
  customer_id INT(11) DEFAULT NULL,
  inactive TINYINT(1) DEFAULT 0,
  first_name VARCHAR(50) DEFAULT NULL,
  last_name VARCHAR(50) DEFAULT NULL,
  PRIMARY KEY (contact_id),
  UNIQUE INDEX contact_key (customer_id, last_name, first_name),
  INDEX customer_id (customer_id),
  INDEX inactive (inactive),
  INDEX name (last_name, first_name),
  CONSTRAINT fk_contacts_customers_customer_id FOREIGN KEY (customer_id)
  REFERENCES customers (customer_id) ON DELETE RESTRICT ON UPDATE CASCADE
)
ENGINE = INNODB
CHARACTER SET utf8
COLLATE utf8_general_ci;

Another goal I have is to setup indexes to make listing all jobs that are not void (status_void=0) and all customers and contacts that are not inactive(inactive=0). 我的另一个目标是设置索引,以列出所有非空的作业(status_void = 0)以及所有非活动的客户和联系人(非活动= 0)。 I don't know if a multi-column index (jobs) or two separate indexes (customers/contacts) would help in this case. 我不知道在这种情况下,多列索引(职位)或两个单独的索引(客户/联系人)是否会有所帮助。

Please take it easy on me as I'm still learning. 我仍在学习,请放轻松。 Thank you for your time. 感谢您的时间。

Is this possible to do with foreign keys or will I have to do the verification in the programming language of my choice? 这可能与外键有关吗?还是我必须使用自己选择的编程语言来进行验证?

Yes and yes. 是的,是的。

This is the referential integrity that FKs add to your data. 这是FK添加到您的数据的参照完整性。 However if you do not also account for it in your application, you would present a horrible user experience that would allow a user to enter contacts that don't belong to a customer and after submitting that to the DB getting an error. 但是,如果您在应用程序中也没有考虑到这一点,则会带来可怕的用户体验,使用户可以输入不属于客户的联系人,并将其提交给数据库后会出错。 It would be better to account for this in you application to prevent that situation from ever being sent to the DB, and the FK is kind of a back-up in case that somehow gets through. 最好在您的应用程序中考虑到这一点,以防止这种情况永远发送到数据库,并且FK是某种备份,以防万一。

Another goal I have is to setup indexes to make listing all jobs that are not void (status_void=0) and all customers and contacts that are not inactive(inactive=0). 我的另一个目标是设置索引,以列出所有非空的作业(status_void = 0)以及所有非活动的客户和联系人(非活动= 0)。 I don't know if a multi-column index (jobs) or two separate indexes (customers/contacts) would help in this case. 我不知道在这种情况下,多列索引(职位)或两个单独的索引(客户/联系人)是否会有所帮助。

Which indexes to build tends to be query specific. 建立哪些索引往往是特定于查询的。 So you would want to show an example query to best get advice in indexing, not just what your end goal is. 因此,您想要显示一个示例查询,以最好地从索引中获得建议,而不仅仅是最终目标是什么。 It's important to know that only one index can be used for each table reference in a query. 重要的是要知道,查询中的每个表引用只能使用一个索引。 So if a table has multiple filters in the where clause you tend to get the best performance by having a multi-column index. 因此,如果一个表在where子句中具有多个过滤器,则您倾向于通过具有多列索引来获得最佳性能。

When planning your indexes it's a good idea to think about which columns have fewer unique values that would filter out a larger number of rows and list those first in the index. 在计划索引时,最好考虑哪些列具有较少的唯一值,这些唯一值会过滤出更多的行并在索引中列出第一行。

All of that being said, without a representative query and the results of an explain statement on it, an outsider can't do much to advise you on indexes as their effectiveness is dependent on the data they are being used against. 综上所述,如果没有代表性查询和有关解释说明的结果,局外人就索引的有效性取决于所使用的数据,无法为您提供很多建议。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM