2010-06-29 60 views
0

HI全部你能說出這個查詢有什麼問題嗎?

我正在使用單個數據庫和近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

是索引的url字段?什麼是「tfdata.web」? – 2010-06-29 07:10:39

+0

@Lasse V. Karlsen ....對不起,這是一個錯誤,我糾正它 – mathew 2010-06-29 07:21:53

+0

和mysql_error是... – Leo 2010-06-29 07:23:49

回答

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_typeSIMPLE,這意味着沒有JOIN語句可以減慢速度。

typeconst,這意味着表至多有一個可能匹配 - 這是得益於UNIQUE指數,從而保證沒有兩個網址將是相同的(見mysql 5.0 indexes - Unique vs Non UniqueUNIQUE INDEX一個很好的說明)。 type列中的const值與您所能得到的值差不多。

possible_keyskey使用url鍵。這意味着每個表格都使用了正確的索引。

refconst,這意味着MySQL正在比較一個常數值(不會改變的)與索引。再次,這是非常快的。

rows等於1. MySQL只需要查看每個表的一行。再一次,這是非常快的。

ExtraUsing index。 MySQL不必對錶進行任何額外的非索引搜索。

如果您在每張表的url列上有索引,您的查詢應該是會非常快。

+0

我收到此錯誤 錯誤 SQL查詢: CREATE PROCEDURE test.autofill( )BEGIN DECLARE我整數默認5; MySQL說:文檔 #1064 - 你的SQL語法有錯誤;檢查與你的MySQL服務器版本相對應的手冊,在第3行 – mathew 2010-06-29 12:21:33

+0

hey done附近使用正確的語法。「我得到了確切的結果,你顯示了......這是否意味着一切都好?那麼我需要改變我的表的整個結構....但如果它很快,那麼我很高興 – mathew 2010-06-29 12:33:27

+0

@mathew:錯誤1064指的是使用[保留字](http://dev.mysql的.com/DOC/refman/5.0/EN /保留-words.html)。你使用的是什麼版本的MySQL?您是否按照原樣複製和粘貼該功能,並使用「DELIMITER」語句完成? – Mike 2010-06-29 12:34:26

0

這聽起來可能有些你WHERE子句中的列是不是indexed。索引用於快速查找具有特定列值的行。如果沒有索引,MySQL必須從第一行開始,然後讀取整個表以查找相關行。

您可能會發現EXPLAIN有助於分析您的查詢。

+0

我已經完成列'url'上的所有表的索引,並且我查詢了EXPLAIN並且它返回了整個表結構......但是我需要從中理解? – mathew 2010-06-29 07:23:58

+0

哦,我爲URL列添加了UNIQUE INDEX。因爲我不想重複......這是否會造成任何干擾? – mathew 2010-06-29 07:27:59

+0

UNIQUE INDEX是一個索引。至於理解EXPLAIN,請查看http://www.databasejournal.com/features/mysql/article.php/1382791/Optimizing-MySQL-Queries-and-Indexes.htm – 2010-06-29 07:35:53

0

肯定看起來像每個表中的URL字段的索引是去

0

[查詢加入,尤其是看差異的方式之間的內部連接,左連接和外部連接。同時指定您要查找的所有字段。

0

可能是您的索引有問題!

在任何情況下,像url這樣的長字符串都會導致表現不佳的主鍵。在索引中佔據了很多空間,因此索引並不像它們可能那樣密集,並且每個IO加載更少的行指針。另外,在網址中,99%的字符串以「http://www」開頭。因此數據庫引擎在決定行不匹配之前必須比較13個字符。

解決此問題的一個方法是使用一些散列函數,如MD5,SHA1甚至CRC32從您的字符串中獲取原始二進制值,並將此值用作表的主鍵。 CRC32提供了一個很好的整數大小的主鍵,但幾乎可以肯定的是,在某個階段,您會遇到兩個散列到相同CRC32值的URL,因此您需要存儲和比較「url」字符串以確保它。其他散列函數返回更長的值(在「原始」模式下分別爲16字節和20字節),但碰撞的機率非常小,不值得擔心。

+0

其實http:// www。在進入數據庫之前被修剪掉 – mathew 2010-06-29 08:29:07

+1

@mathew剝離www是一個錯誤。例如,www.somedomain。com與somedomain.com不一樣。是的,現在大多數網站的DNS條目都指向同一個Web服務器,但這只是一個慣例。無論如何,從URL中剝離3個字符不會大大縮短大多數URL。 – 2010-06-29 08:48:13