我有一张450000排新闻的桌子。 表模式如下:
CREATE TABLE IF NOT EXISTS `news` (
`id` int(11) NOT NULL auto_increment,
`cat_id` int(11) NOT NULL,
`title` tinytext NOT NULL,
`content` text NOT NULL,
`date` int(11) NOT NULL,
`readcount` int(11) NOT NULL default '0',
PRIMARY KEY (`id`),
KEY `cat_id` (`cat_id`),
KEY `cat_id_2` (`cat_id`,`id`),
KEY `cat_id_date` (`cat_id`,`date`)
) ENGINE=MyISAM DEFAULT CHARSET=latin5 AUTO_INCREMENT=462679 ;
当我运行如下的sql命令为类别页面的页面“x”获取一些新闻时,如果x超过100则需要超过15秒:
select * news where cat_id='4' order by id desc limit 150000,10;
解释说明它使用“where”和索引“cat_id_2”
在写这个问题时,我还检查了一个更简单的SQL查询,这也花了近一分钟:
select * from haberler order by id desc limit 40000,10;
如果sql与以下一样,只需几毫秒:
select * from haberler order by id desc limit 20,10;
我的my.cnf配置是这样的:
skip-locking
skip-innodb
query_cache_limit=1M
query_cache_size=256M
query_cache_type=1
max_connections=30
interactive_timeout=600000
#wait_timeout=5
#connect_timeout=5
thread_cache_size=384
key_buffer=256M
join_buffer=4M
max_allowed_packet=16M
table_cache=1024
record_buffer=1M
sort_buffer_size=64M
read_buffer_size=16M
max_connect_errors=10
# Try number of CPU's*2 for thread_concurrency
thread_concurrency=2
myisam_sort_buffer_size=128M
long_query_time = 1
log_slow_queries = /var/log/mysql/mysql-slow.log
max_heap_table_size=512M
该网站运行在core2duo上,内存为2GB。 我认为问题可能是由sort_buffer_size引起的,但我不确定。 提前谢谢。
答案 0 :(得分:18)
<强>更新强>
在我的博客中查看此文章,了解有关该问题的更详细分析:
当您发出LIMIT 150000, 10
之类的内容时,这意味着MySQL
应该遍历这些150,000
条记录并找到下一个10
。
在MySQL
中遍历索引很慢。
此外,MySQL
无法进行后期行查找。
理论上,如果您执行ORDER BY id LIMIT 100000, 10
,则使用索引查找100000
到100010
的值就足够了,然后只查找满足10
行的MySQL
行那个索引并将它们归还。
除MySQL
之外的所有主要系统都知道它并且只有在真正要返回值时才查看行。
SELECT news.*
FROM (
SELECT id
FROM news
WHERE cat_id='4'
ORDER BY
id DESC
LIMIT 150000, 10
) o
JOIN news
ON news.id = o.id
会查找每一行。
尝试重写您的查询:
{{1}}