优化MySQL查询

时间:2011-03-09 00:30:43

标签: mysql optimization

我有一个存储产品的数据库。两个最大的表是我的产品表和图像表。 产品:~19,000行

图片:~34.000行

分类:~60行

原始类别:~1200行

品牌:700行

(其他表格只有几行)

我还有一个包含品牌,原始类别,静态类别的表格(原始类别映射到静态类别)。

我创建了一个Product VIEW来收集我需要的数据,如下所示:

CREATE OR REPLACE VIEW `jos_clothes_view_products` AS
SELECT tbl.*, r.name AS reseller, b.name AS brand, rcat.raw_name AS cats_raw, cats1.name AS cat1, cats1.slug AS catslug1, cats2.name AS cat2, cats2.slug AS catslug2
FROM `jos_clothes_products` AS tbl
LEFT JOIN `jos_clothes_brands` AS b ON b.clothes_brand_id = tbl.clothes_brand_id
LEFT JOIN `jos_clothes_resellers` AS r ON r.clothes_reseller_id = tbl.clothes_reseller_id
LEFT JOIN `jos_clothes_catraws` AS rcat ON rcat.clothes_catraw_id = tbl.clothes_catraw_id
LEFT JOIN `jos_clothes_categories` AS cats2 ON cats2.clothes_category_id = rcat.clothes_category_id
LEFT JOIN `jos_clothes_categories` AS cats1 ON cats1.clothes_category_id = cats2.parent_id

然后从PHP运行这样的查询时:

SELECT `tbl`.* FROM `jos_clothes_view_products` AS `tbl` WHERE  `tbl`.`cat1` != 'NULL' AND `tbl`.`enabled` = '1' ORDER BY `created_on` DESC , `ordering` ASC LIMIT 0 , 20;

查询通常很慢!并非总是如此(可能是因为缓存?)。我还注意到它创建了一个大约200MB的tmp表。有时候它会变得更大并且因“文件无效密钥......”而失败。

我可以如何优化查询?或者实际上是VIEW,我猜这是瓶颈。正确的吗?

产品表结构:

CREATE TABLE IF NOT EXISTS `jos_clothes_products` (
  `clothes_product_id` bigint(20) unsigned NOT NULL auto_increment,
  `clothes_reseller_id` bigint(20) unsigned NOT NULL,
  `aff_prod_id` varchar(50) NOT NULL,
  `title` varchar(255) NOT NULL,
  `description` text NOT NULL,
  `gender` varchar(20) NOT NULL,
  `clothes_brand_id` bigint(20) unsigned NOT NULL,
  `color` varchar(255) NOT NULL,
  `size` varchar(50) NOT NULL,
  `clothes_catraw_id` bigint(20) unsigned NOT NULL,
  `price` decimal(10,2) NOT NULL default '0.00',
  `shipping_cost` varchar(20) NOT NULL default '0.00',
  `currency` varchar(10) NOT NULL,
  `availibility` tinyint(1) NOT NULL,
  `product_url` varchar(350) NOT NULL,
  `real_url` varchar(300) NOT NULL,
  `slug` varchar(255) NOT NULL,
  `hits` int(11) NOT NULL,
  `enabled` tinyint(1) NOT NULL default '0',
  `access` int(11) NOT NULL default '0',
  `ordering` bigint(20) unsigned NOT NULL,
  `created_on` datetime NOT NULL default '0000-00-00 00:00:00',
  `created_by` int(11) NOT NULL default '0',
  `modified_on` datetime NOT NULL default '0000-00-00 00:00:00',
  `modified_by` int(11) NOT NULL default '0',
  `locked_on` datetime NOT NULL default '0000-00-00 00:00:00',
  `locked_by` int(11) NOT NULL default '0',
  PRIMARY KEY  (`clothes_product_id`),
  KEY `clothes_brand_id` (`clothes_brand_id`),
  KEY `clothes_catraw_id` (`clothes_catraw_id`),
  KEY `created_on` (`created_on`),
  KEY `clothes_reseller_id` (`clothes_reseller_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=18962 ;

有什么想法吗?

最好的问候

编辑:jos_clothes_catraws的结构

--
-- Struktur för tabell `jos_clothes_catraws`
--

CREATE TABLE IF NOT EXISTS `jos_clothes_catraws` (
  `clothes_catraw_id` int(11) unsigned NOT NULL auto_increment,
  `clothes_category_id` int(11) unsigned NOT NULL default '0',
  `clothes_reseller_id` int(11) unsigned NOT NULL,
  `raw_name` varchar(255) NOT NULL,
  PRIMARY KEY  (`clothes_catraw_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1289 ;

1 个答案:

答案 0 :(得分:0)

查看您的EXPLAIN输出,看起来罪魁祸首是jos_clothes_catraws表,它没有使用任何索引来进行连接。这是生成大临时表的那个。首先检查表格是否有clothes_catraw_id的密钥。

您还可以使用USE INDEX语法强制使用索引或在表上执行ANALYZE TABLE以确保更新表统计信息,以避免临时表。

我能看到的另一点是你在PHP中使用的查询中的升序和降序的混合。尝试对created_on字段使用降序键,最好使用两个字段的组合键。

同时尝试直接运行查询而不是通过视图,因为MySQL Restrictions on Views section中提到某些视图可能不使用索引,尽管实际语句可以使用索引。