我遇到了困难,因为游戏网站上的数据库结构类似于http://box10.com。 我试图稍微改变一下表结构,但我做得更糟,现在我不能再犯另一个错误来保持我的客户端。所以我很害怕做出任何改变。 如果你能帮助我,我将非常感激。我不想在配置上写下我的知识,而不是花更多的时间。
有两个与我的问题相关的表格。
CREATE TABLE `_games` (
`id` INT(6) NOT NULL AUTO_INCREMENT,
`title` VARCHAR(100) NOT NULL,
`perma` VARCHAR(100) NOT NULL,
`approve` TINYINT(1) NOT NULL DEFAULT '0',
`tags` MEDIUMTEXT NOT NULL,
`description` MEDIUMTEXT NOT NULL,
INDEX `id` (`id`),
INDEX `approve` (`approve`),
FULLTEXT INDEX `ad` (`title`)
)
ENGINE=MyISAM
ROW_FORMAT=DEFAULT
AUTO_INCREMENT=15000
CREATE TABLE `_searches` (
`id` INT(10) NOT NULL AUTO_INCREMENT,
`term` VARCHAR(200) NOT NULL DEFAULT '',
`viewcount` INT(10) NOT NULL DEFAULT '0',
`date` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`)
)
ENGINE=InnoDB
ROW_FORMAT=DEFAULT
AUTO_INCREMENT=450000
_searches table的用法:
在搜索页面上,如果术语不存在,我会将搜索词插入_searches表。如果它存在,那么我更新日期和viewcount。
$date = date("Y-m-d G:i:s");
$c = mysql_query("SELECT id FROM _searches WHERE term='$term'");
if (mysql_num_rows($c) == 1) {
mysql_query("update _searches set viewcount=viewcount+1,date='$date' WHERE term='$term'");
} else {
mysql_query("insert into _searches (term,viewcount,date) values ('$term',1,'$date')");
}
当我使用上面的代码时,mysqld CPU使用率从%50上升到%500左右,负载从0.7上升到7。 你能否请一些建议来帮助我?
_games表的用法:
在标签页面上,我使用以下sql来获取记录:(例如y8.com/tags/Action)
SELECT title,perma FROM _games WHERE tags LIKE '%action,%' AND approve=0 order by id desc LIMIT 0, 20
在搜索页面上搜索游戏:
SELECT perma,title, MATCH(title) AGAINST('$term') AS sort
FROM _games WHERE MATCH(title) AGAINST('$term' IN BOOLEAN MODE) and approve=0
ORDER BY sort DESC limit 10
在游戏页面的“相关游戏”部分:(例如http://www.oyunlar1.com/online.php?flash=5661)
SELECT perma,title, MATCH(title) AGAINST('mario kills the bad guy') AS sort
FROM _games WHERE MATCH(title) AGAINST('mario kills the bad guy' IN BOOLEAN MODE) and approve=0
ORDER BY sort DESC limit 10
在主页上获取记录:
SELECT title,perma FROM _games where approve=0 order by id desc LIMIT 0,28
在游戏页面上获取游戏信息:
SELECT title,description FROM _games WHERE perma='mario-kills-the-bad-guy' AND approve=0
my.cnf档案:
[mysqld]
set-variable=local-infile=0
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
# Default to using old password format for compatibility with mysql 3.x
# clients (those using the mysqlclient10 compatibility package).
old_passwords=1
# Performance optimization
skip-external-locking
max_connections = 300
key_buffer = 8M
sort_buffer = 1M
join_buffer_size = 256K
max_allowed_packet = 1M
thread_stack = 128K
thread_cache_size = 2
table_cache = 1024
thread_concurrency = 2
query_cache_limit = 128k
query_cache_size = 4M
# InnoDB optimization
innodb_file_per_table
innodb_flush_log_at_trx_commit = 0
innodb_lock_wait_timeout = 30
innodb_thread_concurrency = 2
innodb_locks_unsafe_for_binlog = 1
innodb_table_locks = 0
innodb_log_file_size = 2M
innodb_buffer_pool_size = 128M
# !!!! do not change next 2 values !!!!
# data will get destroyed unless you backup everything before changing and then import it back.
innodb_additional_mem_pool_size = 32M
innodb_log_buffer_size = 256k
# Disabling symbolic-links is recommended to prevent assorted security risks;
# to do so, uncomment this line:
# symbolic-links=0
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
服务器
CentOS 5(64位)(CEN564)Plesk 9.5
Quad-Xeon 3220 / 8GB内存/ 2x250GB SATAII / 10TB BW / 1GiGE / 8 IPS(SoftLayer)
MySQL 5.0.77
服务器每天收到大约500,000次综合浏览量。
我愿意接受各种建议,谢谢你的时间。
答案 0 :(得分:4)
您的_searches表的一个明显问题是您搜索的“term”列上没有索引。所以你应该首先添加一个索引(也许也是唯一的,我将在下面解释原因)
即:
CREATE [UNIQUE] INDEX IX_Term on _searches(term);
这将大大加快您的选择查询速度。您还可以使用INSERT DELAYED
(http://dev.mysql.com/doc/refman/5.5/en/insert-delayed.html)和ON DUPLICATE KEY UPDATE
来改进if语句(http:/ /dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html)。为此,你需要一个独特的术语指数。所以查询可以是:
INSERT DELAYED INTO _searches (term, viewcount,date) VALUES ('$term', 1, '$date') ON DUPLICATE KEY UPDATE viewcount = viewcount + 1;
请注意,应该转义$ term和$ date以避免SQL注入
上述查询的作用是在表中插入一个新行但如果该术语已存在(受UNIQUE INDEX限制)而不是插入它将更新将viewcount递增1的现有行。
另请注意,UPDATES可以锁定您的表,限制未来的INSERTS,如果您的_searches表变得太大,这可能很容易导致数据库死锁。
答案 1 :(得分:0)
而不是
$c = mysql_query("SELECT id FROM _searches WHERE term='$term'");
if (mysql_num_rows($c) == 1) {
mysql_query("update _searches set viewcount=viewcount+1,date='$date' WHERE term='$term'");
} else {
mysql_query("insert into _searches (term,viewcount,date) values ('$term',1,'$date')");
}
你可以写
mysql_query("insert into _searches (term,viewcount,date) values ('$term',1,'$date') on duplicate key update viewcount=viewcount+1, date=$date")
我也看到,你在“term”字段中没有索引...从非索引字段中选择也会导致这个问题..
永远不要忘记,全文搜索总是很慢...你可以安装一个全文搜索引擎,如sphinx(http://sphinxsearch.com/)或solr(http://lucene.apache.org/solr/),还可以使用memcache缓存到内存或apc肯定会帮助你。