Php 提高MySQL查询速度

Php 提高MySQL查询速度,php,mysql,Php,Mysql,编辑: 我对查询进行了如下修改: SELECT a.title, count(*),at.search_code FROM `qitz3_attributes_type` at left join qitz3_attributes a on a.attribute_type_id = at.id left join qitz3_attributes_property ap on ap.attribute_id = a.id left join qitz3_hell

编辑:

我对查询进行了如下修改:

SELECT
  a.title, count(*),at.search_code
FROM 
  `qitz3_attributes_type` at
left join
  qitz3_attributes a
on 
  a.attribute_type_id = at.id
left join
  qitz3_attributes_property ap
on
  ap.attribute_id = a.id
left join
  qitz3_helloworld h
on
  h.id = ap.property_id
where 
  at.id in (1,2,8,9,11)
and 
  a.search_filter = 1
and
  h.area=506
and 
  h.expiry_date >= '2013-02-20 13:28:04' 
group by 
  a.title
order by search_code
这似乎快得多,但我仍然得到一个使用临时和使用文件排序的解释

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  at  range   PRIMARY PRIMARY 4   NULL    5   Using where; Using temporary; Using filesort
1   SIMPLE  a   ref PRIMARY,Attribute type ID,Search filter,Attribute ...   Attribute type ID   4   password.at.id  6   Using where
1   SIMPLE  ap  ref Property ID,Attribute ID,Attribute Property Attribute Property  4   password.a.id   142 Using where; Using index
1   SIMPLE  h   eq_ref  PRIMARY,Area indexes,Expiry date    PRIMARY 4   password.ap.property_id 1   Using where
恩迪特

我正在为我正在开发的一个网站开发一个搜索组件,虽然它都在工作,但有几个查询我希望运行得更快一些

为了填充一组搜索过滤器(显示具有每个设施或特定类型的属性数量的计数),我使用以下两个查询。第一个将获得ID列表,然后将其插入第二个查询,如下所示:

SELECT
  a.title, count(*),at.search_code
FROM 
  `qitz3_attributes_type` at
left join
  qitz3_attributes a
on 
  a.attribute_type_id = at.id
left join
  qitz3_attributes_property ap
on
  ap.attribute_id = a.id
left join
  qitz3_helloworld h
on
  h.id = ap.property_id
where 
  at.id in (1,2,8,9,11)
and 
  a.search_filter = 1
and
  h.area=506
and 
  h.expiry_date >= '2013-02-20 13:28:04' 
group by 
  a.title
order by search_code
根据以下信息,有人能提出更有效的方法吗?我真的想加快第一个查询的速度,因为与其他查询相比,它似乎有点慢

150毫秒真的那么慢吗?15毫秒会更好

谢谢

亚当

查询1(大约需要150毫秒):

说明:

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   PRIMARY c   const   PRIMARY PRIMARY 4   const   1   
1   PRIMARY h   ref PRIMARY,Area indexes,Expiry date    Area indexes    4   const   615 Using where
1   PRIMARY ap  ref Property ID,Attribute ID    Property ID 4   password.h.id   21  Using where
1   PRIMARY at  eq_ref  PRIMARY PRIMARY 4   password.ap.attribute_id    1   Using index
1   PRIMARY a   eq_ref  PRIMARY,Attribute type ID   PRIMARY 4   password.ap.attribute_id    1   Using where
1   PRIMARY ap2 ref Property ID,Attribute ID    Property ID 4   password.ap.property_id 21  Using where
1   PRIMARY at2 eq_ref  PRIMARY PRIMARY 4   password.ap2.attribute_id   1   Using index
1   PRIMARY a2  eq_ref  PRIMARY,Attribute type ID   PRIMARY 4   password.ap2.attribute_id   1   Using where
1   PRIMARY e   eq_ref  PRIMARY PRIMARY 4   password.h.tariff_based_on  1   
1   PRIMARY f   eq_ref  PRIMARY PRIMARY 4   password.h.base_currency    1   
1   PRIMARY g   eq_ref  PRIMARY PRIMARY 4   password.h.city 1   
3   DEPENDENT SUBQUERY  qitz3_reviews   ref Property ID Property ID 4   password.h.id   1   Using index; Using temporary; Using filesort
2   DEPENDENT SUBQUERY  qitz3_tariffs   ref Property ID Property ID 4   password.h.id   2         
查询2(大约需要30毫秒):

此查询提供每个属性(例如高尔夫、空调、属性类型等)的属性数量计数。这样做的好处是只显示具有属性的属性。因此,当用户向下搜索时,不显示任何属性的属性。这基本上是第一个查询,在这里我得到了一个属性列表,这些属性与一组特定的属性相匹配

各表如下:

SELECT
  a.title, count(*),at.search_code
FROM 
  `qitz3_attributes_type` at
left join
  qitz3_attributes a
on 
  a.attribute_type_id = at.id
left join
  qitz3_attributes_property ap
on
  ap.attribute_id = a.id
left join
  qitz3_helloworld h
on
  h.id = ap.property_id
where 
  at.id in (1,2,8,9,11)
and 
  a.search_filter = 1
and
  h.area=506
and 
  h.expiry_date >= '2013-02-20 13:28:04' 
group by 
  a.title
order by search_code
--

--表
qitz3\u属性的表结构
--

--表的表结构
qitz3\u属性\u属性
--

--表的表结构
qitz3\u属性\u类型
--

--表的表结构
qitz3\U分类
--

--表的表结构(属性表) --

--表的表结构
qitz3\U审查
--

--表的表结构
qitz3\U关税

当您需要更快地搜索数据时,您应该查看或。使用此索引服务器,您可以索引MySQL数据并查询它们


它比MySQL快得多。

快速播放,但尝试将子选择从字段列表中移出

SELECT h.id, h.parent_id, h.level, h.title as property_title, h.area, h.region, h.department, h.city, LEFT(h.description, 250) as description, h.thumbnail, h.occupancy, h.swimming, g.path, (single_bedrooms + double_bedrooms + triple_bedrooms + quad_bedrooms + twin_bedrooms) as bedrooms, c.title as location_title, 
Sub1.price, 
e.title as tariff_based_on, f.title as base_currency, a.title as property_type, a2.title as accommodation_type, 
Sub2.reviews 
FROM qitz3_classifications c 
LEFT JOIN qitz3_helloworld h on c.id = h.area 
LEFT JOIN qitz3_attributes_property ap ON ap.property_id = h.id 
LEFT JOIN qitz3_attributes_type at ON at.id = ap.attribute_id 
LEFT JOIN qitz3_attributes a ON a.id = ap.attribute_id 
LEFT JOIN qitz3_attributes_property ap2 ON ap2.property_id = h.id 
LEFT JOIN qitz3_attributes_type at2 ON at2.id = ap2.attribute_id 
LEFT JOIN qitz3_attributes a2 ON a2.id = ap2.attribute_id 
LEFT JOIN qitz3_attributes e ON e.id = h.tariff_based_on 
LEFT JOIN qitz3_attributes f ON f.id = h.base_currency 
LEFT JOIN qitz3_classifications g ON g.id = h.city 
LEFT JOIN ( SELECT id, MIN(tariff) AS price FROM qitz3_tariffs GROUP BY id) Sub1 ON Sub1.Id = h.id 
LEFT JOIN ( SELECT property_id, COUNT(*) AS reviews FROM qitz3_reviews GROUP BY property_id ) as Sub2 ON Sub2.property_id = h.id 
WHERE a.attribute_type_id = 1 
AND a2.attribute_type_id = 2 
AND c.id = 506 
AND h.expiry_date >= '2013-02-20 12:05:13' 
AND h.id > 1 

您的第一个查询中有很多错误:


前7个左联接应该是内部联接。对于QITZ3BY属性,您应该考虑不那么积极地规范数据(使用多个列而不是多行来描述数据)。请输入一些示例DATACAN,您可以在子选择(QITZ3X关税和QITZ3X评论)中使用2个表的表定义。请?我会的。但是,你看到我的编辑了吗?我写了一个不同的查询,速度更快,但仍然会导致解释中可怕的“使用文件排序,使用临时”。看到我的编辑了吗?事实上,在我发布的最初方案中,我只需要ID列表,而不需要任何其他字段!只是添加了额外的表定义。你知道吗qitz3_attributes_类型(~34)上没有太多行。MySQL可能会忽略所需排序的索引,因为它使用了约15%的记录,而且扫描表比使用索引更快。这似乎不起作用,事实上似乎会使它变慢。它不起作用(即,错误)或者它在工作时会变慢?抱歉,它确实有效,但它会变慢。足够公平。可能值得在没有子选择的情况下尝试。只是为了看看它们是否对性能有真正的影响。但是,再次查看您最初的解释,我很惊讶它选择在区域/地区/部门上使用索引。可能值得尝试在c中添加索引检查到期日(假设存在大量具有旧到期日的记录)。给定MySQL在一个表上只使用一个索引,尝试在area和expiry date列上添加一个索引。同意,该查询不太好。使用内部联接时运行速度稍快,但仍然超过100ms。我刚刚发布了一个不同的查询,它似乎更好…如果我希望一个属性具有多个属性,如何使用多个列?同意,我同意我会将一些枚举类型添加到属性表中,但我看不出如何为所有属性添加枚举类型
CREATE TABLE IF NOT EXISTS `qitz3_attributes_property` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`property_id` int(11) NOT NULL,
`attribute_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `Property ID` (`property_id`),
KEY `Attribute ID` (`attribute_id`)
) ENGINE=InnoDB    DEFAULT CHARSET=latin1 AUTO_INCREMENT=66261 ;
CREATE TABLE IF NOT EXISTS `qitz3_attributes_type` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(75) NOT NULL,
`language_code` varchar(6) NOT NULL,
`field_name` varchar(25) NOT NULL,
`search_code` varchar(25) NOT NULL,
`state` int(11) NOT NULL DEFAULT '1',
`published` int(11) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`)
) ENGINE=InnoDB    DEFAULT CHARSET=latin1 AUTO_INCREMENT=34 ;
CREATE TABLE IF NOT EXISTS `qitz3_classifications` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`parent_id` int(10) unsigned NOT NULL DEFAULT '0',
`lft` int(11) NOT NULL DEFAULT '0',
`rgt` int(11) NOT NULL DEFAULT '0',
`level` int(10) unsigned NOT NULL DEFAULT '0',
`title` varchar(255) NOT NULL,
`description` text NOT NULL,
`path` varchar(255) NOT NULL DEFAULT '',
`alias` varchar(255) NOT NULL,
`access` tinyint(3) unsigned NOT NULL DEFAULT '0',
`published` int(11) NOT NULL,
`longitude` float(10,6) NOT NULL,
`latitude` float(10,6) NOT NULL,
PRIMARY KEY (`id`),
KEY `idx_left_right` (`lft`,`rgt`),
KEY `Alias index` (`alias`)
) ENGINE=MyISAM    DEFAULT CHARSET=utf8 AUTO_INCREMENT=158052 ;
CREATE TABLE IF NOT EXISTS `qitz3_helloworld` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`parent_id` int(10) NOT NULL DEFAULT '0',
`lft` int(11) NOT NULL DEFAULT '0',
`rgt` int(11) NOT NULL DEFAULT '0',
`level` int(10) unsigned NOT NULL,
`alias` varchar(250) NOT NULL DEFAULT '',
`access` tinyint(3) unsigned NOT NULL DEFAULT '0',
`path` varchar(255) NOT NULL DEFAULT '',
`title` varchar(120) NOT NULL,
`area` int(11) NOT NULL DEFAULT '0',
`region` int(11) NOT NULL DEFAULT '0',
`department` int(11) NOT NULL DEFAULT '0',
`city` int(11) NOT NULL DEFAULT '0',
`params` text NOT NULL,
`created_by` int(10) NOT NULL DEFAULT '0',
`created_on` datetime NOT NULL,
`modified` datetime DEFAULT NULL,
`expiry_date` date DEFAULT NULL,
`availability_last_updated_on` datetime DEFAULT NULL,
`modified_by` int(11) DEFAULT NULL,
`lang` varchar(5) NOT NULL DEFAULT 'en-GB',
`description` mediumtext NOT NULL COMMENT 'The summary and description for this accommodation',
`internal_facilities_other` varchar(1000) NOT NULL,
`external_facilities_other` varchar(1000) NOT NULL,
`activities_other` varchar(5000) NOT NULL,
`location_details` varchar(5000) NOT NULL,
`getting_there` varchar(5000) NOT NULL,
`thumbnail` varchar(150) NOT NULL,
`occupancy` int(11) DEFAULT NULL,
`single_bedrooms` int(11) NOT NULL,
`double_bedrooms` int(11) NOT NULL,
`triple_bedrooms` int(11) DEFAULT NULL,
`quad_bedrooms` int(11) DEFAULT NULL,
`twin_bedrooms` int(11) DEFAULT NULL,
`childrens_beds` int(11) DEFAULT NULL,
`cots` int(11) DEFAULT NULL,
`extra_beds` int(11) DEFAULT NULL,
`bathrooms` int(11) NOT NULL,
`toilets` int(11) DEFAULT NULL,
`swimming` int(11) NOT NULL,
`latitude` decimal(10,7) DEFAULT NULL,
`longitude` decimal(10,7) DEFAULT NULL,
`nearest_town` varchar(50) DEFAULT NULL,
`distance_to_coast` int(11) DEFAULT NULL,
`additional_price_notes` varchar(3000) DEFAULT NULL,
`base_currency` int(11) DEFAULT NULL,
`tariff_based_on` int(11) DEFAULT NULL,
`linen_costs` varchar(250) DEFAULT NULL,
`changeover_day` int(11) DEFAULT NULL,
`published` tinyint(4) NOT NULL DEFAULT '0',
`video` tinyint(4) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `idx_left_right` (`lft`,`rgt`),
KEY `Area indexes` (`area`,`region`,`department`),
KEY `Expiry date` (`expiry_date`)
) ENGINE=InnoDB    DEFAULT CHARSET=utf8 AUTO_INCREMENT=158249 ;
CREATE TABLE IF NOT EXISTS `qitz3_reviews` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`property_id` int(11) NOT NULL,
`title` varchar(150) NOT NULL,
`review_text` varchar(4000) NOT NULL,
`date` date NOT NULL,
`rating` int(11) NOT NULL,
`guest_name` varchar(75) NOT NULL,
`guest_email` varchar(150) NOT NULL,
`state` tinyint(3) NOT NULL DEFAULT '0',
`published` tinyint(1) NOT NULL DEFAULT '0',
`created` datetime NOT NULL,
`created_by` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `Property ID` (`property_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=921 ;
CREATE TABLE IF NOT EXISTS `qitz3_tariffs` (
`tariff_id` int(11) NOT NULL AUTO_INCREMENT,
`id` int(11) NOT NULL COMMENT 'Denotes the property listing ID',
`start_date` date NOT NULL,
`end_date` date NOT NULL,
`tariff` int(11) NOT NULL COMMENT 'Price per booking period between the dates specified. dated spec',
PRIMARY KEY (`tariff_id`),
KEY `Property ID` (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=9267 ;
SELECT h.id, h.parent_id, h.level, h.title as property_title, h.area, h.region, h.department, h.city, LEFT(h.description, 250) as description, h.thumbnail, h.occupancy, h.swimming, g.path, (single_bedrooms + double_bedrooms + triple_bedrooms + quad_bedrooms + twin_bedrooms) as bedrooms, c.title as location_title, 
Sub1.price, 
e.title as tariff_based_on, f.title as base_currency, a.title as property_type, a2.title as accommodation_type, 
Sub2.reviews 
FROM qitz3_classifications c 
LEFT JOIN qitz3_helloworld h on c.id = h.area 
LEFT JOIN qitz3_attributes_property ap ON ap.property_id = h.id 
LEFT JOIN qitz3_attributes_type at ON at.id = ap.attribute_id 
LEFT JOIN qitz3_attributes a ON a.id = ap.attribute_id 
LEFT JOIN qitz3_attributes_property ap2 ON ap2.property_id = h.id 
LEFT JOIN qitz3_attributes_type at2 ON at2.id = ap2.attribute_id 
LEFT JOIN qitz3_attributes a2 ON a2.id = ap2.attribute_id 
LEFT JOIN qitz3_attributes e ON e.id = h.tariff_based_on 
LEFT JOIN qitz3_attributes f ON f.id = h.base_currency 
LEFT JOIN qitz3_classifications g ON g.id = h.city 
LEFT JOIN ( SELECT id, MIN(tariff) AS price FROM qitz3_tariffs GROUP BY id) Sub1 ON Sub1.Id = h.id 
LEFT JOIN ( SELECT property_id, COUNT(*) AS reviews FROM qitz3_reviews GROUP BY property_id ) as Sub2 ON Sub2.property_id = h.id 
WHERE a.attribute_type_id = 1 
AND a2.attribute_type_id = 2 
AND c.id = 506 
AND h.expiry_date >= '2013-02-20 12:05:13' 
AND h.id > 1