我有这张桌子:
CREATE TABLE IF NOT EXISTS `listings` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`type` tinyint(1) NOT NULL DEFAULT '1',
`hash` char(32) NOT NULL,
`source_id` int(10) unsigned NOT NULL,
`link` varchar(255) NOT NULL,
`short_link` varchar(255) NOT NULL,
`cat_id` mediumint(5) NOT NULL,
`title` mediumtext NOT NULL,
`description` mediumtext,
`content` mediumtext,
`images` mediumtext,
`videos` mediumtext,
`views` int(10) NOT NULL,
`comments` int(11) NOT NULL DEFAULT '0',
`comments_update` int(11) NOT NULL DEFAULT '0',
`editor_id` int(11) NOT NULL DEFAULT '0',
`auther_name` varchar(255) DEFAULT NULL,
`createdby_id` int(10) NOT NULL,
`createdon` int(20) NOT NULL,
`editedby_id` int(10) NOT NULL,
`editedon` int(20) NOT NULL,
`deleted` tinyint(1) NOT NULL,
`deletedon` int(20) NOT NULL,
`deletedby_id` int(10) NOT NULL,
`deletedfor` varchar(255) NOT NULL,
`published` tinyint(1) NOT NULL DEFAULT '1',
`publishedon` int(20) NOT NULL,
`publishedby_id` int(10) NOT NULL,
PRIMARY KEY (`id`),
KEY `hash` (`hash`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT AUTO_INCREMENT=91628 ;
和一些像这样的错误查询
SELECT id,type , source_id, link, short_link, cat_id, title,
description, images, views, comments, published, publishedon,
content, comments_update, editor_id, auther_name, createdby_id,
createdon, editedby_id, editedon, deleted, deletedon,
deletedby_id, deletedfor, publishedby_id
FROM listings
WHERE (cat_id IN ( 98 ))
AND (TYPE IN ('1'))
AND (source_id IN ('78'))AND (FROM_UNIXTIME( publishedon ) >= SUBDATE( NOW( ) ,
1 )
)
AND (deleted =0)
AND (published =1)
ORDER BY `publishedon` DESC
LIMIT 10 OFFSET 0
和
SELECT id,type,source_id,link,short_link,cat_id,title,description,
images,views,comments,published,publishedon
FROM listings
WHERE (title RLIKE 'اليمن|عدن')
AND (id != 89024)
AND (deleted = 0)
AND (published = 1)
ORDER BY publishedon DESC
LIMIT 6 OFFSET 0
和
SELECT MIN(id) FROM listings
WHERE (id > 91152) AND (cat_id = '134')
和
SELECT COUNT(id)
FROM listings
WHERE (publishedon >= '1442963362'
AND publishedon <= '1443568162'
)
AND (cat_id IN ('19', '20', '21', '22', '23', '24', '27',
'32', '35', '110', '54', '38', '39', '41', '42', '43',
'44', '45', '46', '47', '49', '56', '57', '51', '55',
'58', '59', '60', '61', '62', '102', '95', '96', '98',
'101', '103', '104', '105', '106', '124', '125', '130',
'131', '132', '133', '134', '135')
)
此查询可能需要0.4秒才能完成。任何在一个页面中,它可能包含5个这样的查询。这是一个非常大的问题;它会导致服务器负载和停机时间。
此查询
SELECT *
FROM `listings`
WHERE id = 5455
需要0.0004秒才能完成,因为它取决于pk的索引
如何在第一个查询中为列创建索引?
很多时候,当我使用&#34; show processlist&#34;时,我看到了这个&#34;等待表级锁定&#34;太多了&#34;排序数据&#34;。
应用程序一直插入/更新许多行;我怎么解决这个问题?
答案 0 :(得分:2)
您的查询基本上是:
SELECT . . .
FROM listings l
WHERE cat_id = 98 AND
TYPE = 1 AND
source_id = 78 AND
deleted = 0 AND
published = 1 AND
FROM_UNIXTIME( publishedon ) >= SUBDATE( NOW( ) , 1 )
ORDER BY `publishedon` DESC
LIMIT 10
OFFSET 0
对于性能,从(cat_id, type, source_id, deleted, published, publishedon)
上的复合索引开始。语法是:
create index idx_listings_6 on listings(cat_id, type, source_id, deleted, published, publishedon desc);
接下来,我建议将where
子句重写为:
SELECT . . .
FROM listings l
WHERE cat_id = 98 AND
TYPE = 1 AND
source_id = 78 AND
deleted = 0 AND
published = 1 AND
publishedon >= UNIX_TIMESTAMP(SUBDATE( NOW( ) , 1 ))
ORDER BY `publishedon` DESC
LIMIT 10
OFFSET 0
并使用上面相同的索引。
答案 1 :(得分:0)
MySQL无法将索引声明为DESC
;它会忽略该关键字并构建ASC
索引。但是,ORDER BY x DESC
仍然可以优化。
MySQL每个SELECT只使用一个INDEX。 (一般)。
最佳索引以&#39; =&#39;的任何WHERE
子句字段开头。
查询1:已经讨论过。
查询2:INDEX(deleted, published, publishedon)
查询3:INDEX(cat_id, id)
问题4:将COUNT(id)
更改为COUNT(*)
并添加INDEX(cat_id, publishedon)
和/或INDEX(publishedon, cat_id)
。不明显哪个指数会更好。添加两者并让优化器决定。与您的其他问题一样,PARTITION BY RANGE(publishedon)
使用INDEX(cat_id, publishedon)
(而非另一个)可能会有所帮助。
考虑切换到InnoDB。