表和查询优化

时间:2015-03-09 00:23:14

标签: mysql select optimization

简单的网络应用程序,使用PHp和MySql后端托管在标准共享主机上。

我有两个相对较小的表(每行几百行),当我使用连接查询时,查询可能需要两到三秒。

这里有一张桌子:'学生':

CREATE TABLE IF NOT EXISTS `students` (
`_id` mediumint(9) NOT NULL AUTO_INCREMENT,
  `firstname` char(30) NOT NULL,
  `lastname` char(30) NOT NULL,
  `dateOfBirth` date DEFAULT NULL,
  `gender` varchar(10) NOT NULL,
  `knownasname` varchar(30) NOT NULL,
  `school` varchar(30) DEFAULT NULL,
  `schoolyear` varchar(30) DEFAULT NULL,
  `notes` text,
  `foundusvia` varchar(30) DEFAULT NULL,
  `dateadded` datetime NOT NULL,
  `archived` tinyint(1) DEFAULT NULL,
  PRIMARY KEY (`_id`),
  UNIQUE KEY `_id` (`_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=684 ;

这是第二个:

CREATE TABLE IF NOT EXISTS `contacts` (
  `_id` mediumint(9) NOT NULL AUTO_INCREMENT,
  `student_id` mediumint(9) NOT NULL,
  `studentAddressStreet` varchar(50) DEFAULT NULL,
  `studentAddressArea` varchar(30) DEFAULT NULL,
  `studentAddressTown` varchar(30) DEFAULT NULL,
  `studentAddressPostcode` varchar(30) DEFAULT NULL,
  `studentPhoneMobile` varchar(30) DEFAULT NULL,
  `studentPhoneLand` varchar(30) DEFAULT NULL,
  `studentAddressNotes` text,
  `studentemail` varchar(50) DEFAULT NULL,
  `billingAddressStreet` varchar(50) DEFAULT NULL,
  `billingAddressArea` varchar(30) DEFAULT NULL,
  `billingAddressTown` varchar(30) DEFAULT NULL,
  `billingAddressPostcode` varchar(30) DEFAULT NULL,
  `billingPhoneMobile` varchar(30) DEFAULT NULL,
  `billingPhoneLand` varchar(30) DEFAULT NULL,
  `billingContactName` varchar(30) DEFAULT NULL,
  `billingContactRelationship` varchar(30) DEFAULT NULL,
  `billingAddressNotes` text,
  `billingemail` varchar(50) DEFAULT NULL,
  `caregiverAddressStreet` varchar(50) DEFAULT NULL,
  `caregiverAddressArea` varchar(30) DEFAULT NULL,
  `caregiverAddressTown` varchar(30) DEFAULT NULL,
  `caregiverAddressPostcode` varchar(30) DEFAULT NULL,
  `caregiverPhoneMobile` varchar(30) DEFAULT NULL,
  `caregiverPhoneLand` varchar(30) DEFAULT NULL,
  `caregiverContactName` varchar(30) DEFAULT NULL,
  `caregiverContactRelationship` varchar(30) DEFAULT NULL,
  `caregiverAddressNotes` text,
  `caregiveremail` varchar(50) DEFAULT NULL,
    PRIMARY KEY (`_id`),
  KEY `contacts_index` (`student_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=290 ;

以下是查询:

它的工作是从表格中获取所有数据"学生'和'联系人'对于有给定_id的学生。

SELECT * 
  FROM students, contacts
 WHERE students._id = contacts.student_id
  AND students._id =99  <=== This value obviously changes

contacts有一个关于student_id的索引

表学生的名字和姓氏都有索引。

使此查询运行需要2到3秒有什么问题?表很小,查询简单。任何帮助非常感谢!!

编辑:这里是EXPLAIN的输出。还修改了联系人表格的CREATE

id | select_type | table   | type | possible_keys | key          | key_len | ref  | rows | Extra
===|=============|=========|======|===============|==============|=========|======|=============
1  |  SIMPLE     | students|const | PRIMARY       | PRIMARY      |  3      |const | 1    |
1  |  SIMPLE     | contacts|ref   | contacts_index|contacts_index|  3      |const | 1    |

1 个答案:

答案 0 :(得分:0)

专业提示:如果可能的话,请避免SELECT *。这在JOIN上尤其成问题。

如果使用标准JOIN,您将更容易阅读查询,如此。在20世纪90年代末的某个时间,以逗号分隔的表jumped the shark列表。

SELECT students.*, 
       contacts.* 
  FROM students
  LEFT JOIN contacts ON students._id = contacts.student_id
 WHERE students._id =99 

最后,在student_id表的contacts列上放置索引,以便联接可以快速访问该表。