全部
我正在使用单个数据库和大约7个表。确实有数据填充所有表格。 说截止到目前为止大约10k左右。但是会进一步增长,可能会花费数百万,但需要时间。
我的问题是我的查询缓慢获取结果的原因。在非负载条件下查询大约需要10到12秒。我担心如果在负载条件下发生的事情一次会说成千上万的查询?
这是我的示例查询...
$result = $db->sql_query("SELECT * FROM table1,table2,table3,table4,table5 WHERE table1.url = table2.url AND table1.url = table3.url AND table1.url = table4.url AND table1.url = table5.url AND table1.url='".$uri."'")or die(mysql_error());
$row = $db->sql_fetchrow($result);
$daysA = $row['regtime'];
$days = (strtotime(date("Y-m-d")) - strtotime($row['regtime'])) / (60 * 60 * 24);
if($row > 0 && $days < 2){
$row['data'];
$row['data1'];
//remaining
}else{ //some code}
答案 0 :(得分:0)
您的WHERE
子句中的某些列可能不是indexed。索引用于快速查找具有特定列值的行。如果没有索引,MySQL必须从第一行开始,然后读取整个表以查找相关行。
您可能会发现EXPLAIN
有助于分析您的查询。
答案 1 :(得分:0)
绝对看起来像每个表中url字段的索引是要走的路
答案 2 :(得分:0)
查找JOIN,特别是看看INNER JOINS,LEFT JOINS和OUTER JOINS之间的区别。同时INDEX您要进行查找的所有字段。
答案 3 :(得分:0)
你的索引可能有问题!
在任何情况下,像url这样的长字符串都会导致主键性能下降。在索引中占用了大量空间,因此索引不像它们那样密集,并且每个IO加载的行指针更少。同样使用网址的可能性是99%的字符串以“http://www开头”。所以数据库引擎在决定一行不匹配之前必须比较13个字符。
对此的一个解决方案是使用一些散列函数(如MD5,SHA1甚至CRC32)从字符串中获取原始二进制值,并将此值用作表的主键。 CRC32是一个很好的整数大小的主键,但几乎可以肯定,在某些阶段你会遇到两个散列到相同CRC32值的url,因此你需要存储和比较“url”字符串。其他散列函数返回更长的值(在“原始”模式下分别为16字节和20字节),但碰撞的可能性非常小,以至于不值得烦恼。
答案 4 :(得分:0)
我不确定你是否已经解决了这个问题,但这里是我制作的一些测试数据。有许多因素会影响查询的速度,因此我的简单测试用例可能无法准确反映您的表或数据。但是,它们是一个有用的起点。
首先,创建5个简单的表,每个表具有相同的结构。与表格一样,我在UNIQUE
列上使用了url
索引:
CREATE TABLE `table1` (
`id` int(11) NOT NULL auto_increment,
`url` varchar(255) default NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `url` (`url`)
) ENGINE=InnoDB;
CREATE TABLE table2 LIKE table1;
CREATE TABLE table3 LIKE table1;
CREATE TABLE table4 LIKE table1;
CREATE TABLE table5 LIKE table1;
以下脚本创建一个存储过程,用于向每个表填充10,000行数据:
DELIMITER //
DROP PROCEDURE IF EXISTS test.autofill//
CREATE PROCEDURE test.autofill()
BEGIN
DECLARE i INT DEFAULT 5;
WHILE i < 10000 DO
INSERT INTO table1 (url) VALUES (CONCAT('wwww.stackoverflow.com/', i ));
INSERT INTO table2 (url) VALUES (CONCAT('wwww.stackoverflow.com/', 10000 - i ));
INSERT INTO table3 (url) VALUES (CONCAT('wwww.stackoverflow.com/', i + 6000 ));
INSERT INTO table4 (url) VALUES (CONCAT('wwww.stackoverflow.com/', i + 3000 ));
INSERT INTO table5 (url) VALUES (CONCAT('wwww.stackoverflow.com/', i + 2000 ));
SET i = i + 1;
END WHILE;
END;
//
DELIMITER ;
CALL test.autofill();
现在每个表包含10,000行。您的SELECT
语句现在可用于查询数据:
SELECT *
FROM table1,table2,table3,table4,table5
WHERE table1.url = table2.url
AND table1.url = table3.url
AND table1.url = table4.url
AND table1.url = table5.url
AND table1.url = 'wwww.stackoverflow.com/8000';
这几乎可以立即得到以下结果:
+------+-----------------------------+------+-----------------------------+------+-----------------------------+------+-----------------------------+------+-----------------------------+
| id | url | id | url | id | url | id | url | id | url |
+------+-----------------------------+------+-----------------------------+------+-----------------------------+------+-----------------------------+------+-----------------------------+
| 7996 | wwww.stackoverflow.com/8000 | 1996 | wwww.stackoverflow.com/8000 | 1996 | wwww.stackoverflow.com/8000 | 4996 | wwww.stackoverflow.com/8000 | 5996 | wwww.stackoverflow.com/8000 |
+------+-----------------------------+------+-----------------------------+------+-----------------------------+------+-----------------------------+------+-----------------------------+
EXPLAIN SELECT
显示查询速度非常快的原因:
EXPLAIN SELECT *
FROM table1,table2,table3,table4,table5
WHERE table1.url = table2.url
AND table1.url = table3.url
AND table1.url = table4.url
AND table1.url = table5.url
AND table1.url = 'wwww.stackoverflow.com/8000';
+----+-------------+--------+-------+---------------+------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+-------+---------------+------+---------+-------+------+-------------+
| 1 | SIMPLE | table1 | const | url | url | 258 | const | 1 | Using index |
| 1 | SIMPLE | table2 | const | url | url | 258 | const | 1 | Using index |
| 1 | SIMPLE | table3 | const | url | url | 258 | const | 1 | Using index |
| 1 | SIMPLE | table4 | const | url | url | 258 | const | 1 | Using index |
| 1 | SIMPLE | table5 | const | url | url | 258 | const | 1 | Using index |
+----+-------------+--------+-------+---------------+------+---------+-------+------+-------------+
select_type
为SIMPLE
,这意味着没有JOIN
语句可以降低速度。
type
是const
,这意味着该表最多只能有一个匹配 - 这要归功于UNIQUE
索引,它保证两个网址不会相同(参见mysql 5.0 indexes - Unique vs Non Unique有关UNIQUE INDEX
)的详细说明。 const
列中的type
值与您可以获得的值相同。
possible_keys
和key
使用url
密钥。这意味着每个表都使用了正确的索引。
ref
是const
,这意味着MySQL正在将一个常量值(一个不变的值)与索引进行比较。再次,这非常快。
rows
等于1. MySQL只需查看每个表中的一行。再一次,这是非常快的。
Extra
是Using index
。 MySQL不必对表进行任何额外的非索引搜索。
如果您在每个表的url
列上都有索引,那么您的查询应该非常快。