2011-11-18 216 views
1

我有一個phpmyadmin數據庫,有1 000 000條記錄需要搜索。每週有500 000條記錄添加。sql查詢很慢

所以,這是我需要的:

location_id value date  time  name    lat  lng 
3   234 2011-11-18 19:50:00 Amerongen beneden 5.40453 51.97486 
4   594 2011-11-18 19:50:00 Amerongen boven  5.41194 51.97507 

我這樣做與此查詢:

SELECT location_id, value, date, time, locations.name, locations.lat, locations.lng FROM 
(
SELECT location_id, value, date, time from `measurements` 
LEFT JOIN units ON (units.id = measurements.unit_id) 
WHERE units.name='Waterhoogte' 
ORDER BY measurements.date DESC, measurements.time DESC 
) as last_record 
LEFT JOIN locations on (locations.id = location_id) 
GROUP BY location_id 

這需要30秒。我該如何改進?這是我的結構:

CREATE TABLE IF NOT EXISTS `locations` (
    `id` int(11) NOT NULL auto_increment, 
    `name` varchar(255) NOT NULL, 
    `code` varchar(255) NOT NULL, 
    `lat` varchar(10) NOT NULL, 
    `lng` varchar(10) NOT NULL, 
    `owner_id` int(11) NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=244 ; 

-- -------------------------------------------------------- 

-- 
-- Table structure for table `measurements` 
-- 

CREATE TABLE IF NOT EXISTS `measurements` (
    `id` int(11) NOT NULL auto_increment, 
    `date` date NOT NULL, 
    `time` time NOT NULL, 
    `value` varchar(255) NOT NULL, 
    `location_id` int(11) NOT NULL, 
    `unit_id` int(11) NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=676801 ; 

-- -------------------------------------------------------- 

-- 
-- Table structure for table `owner` 
-- 

CREATE TABLE IF NOT EXISTS `owner` (
    `id` int(11) NOT NULL auto_increment, 
    `name` varchar(255) NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ; 

-- -------------------------------------------------------- 

-- 
-- Table structure for table `units` 
-- 

CREATE TABLE IF NOT EXISTS `units` (
    `id` int(11) NOT NULL auto_increment, 
    `name` varchar(255) NOT NULL, 
    `description` text NOT NULL, 
    `unit_short` varchar(255) NOT NULL, 
    `owner_id` int(11) NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=44 ; 

什麼是phpmyadmin可以處理的限制?

+1

我想澄清它不是phpmyadmin的限制。這是mySql能夠運行查詢的速度。 – Dallas

+2

注意:phpmyadmin不是數據庫。這是一個基於PHP的** INTERFACE **到mysql數據庫服務器。 –

回答

4

在units.name上創建索引特別是一個好的開始。 你也應該重新考慮你要回退的數據量。 是否有人真的要篩選這麼多記錄。更改您的查詢以限制記錄數量並考慮涉及分頁機制的UI界面。

+0

我將WHERE units.name ='Waterhoogte'替換爲:WHERE units.id = 4,將其降至2秒。有沒有其他方法可以更好地重寫此查詢? – Melvin

+0

你有這個領域的索引嗎?你可能也想要在location.id上有一個索引。最終,你可以做更多的事情來讓你的查詢「更快」。這更多的是你將多少條記錄帶回客戶端的問題。限制並編寫一些漂亮的UI,以便在需要時觸發更多記錄。把這麼多的記錄帶回來只是一個不行。當你做谷歌搜索,它會帶回40頁的結果,在大多數情況下,你只關心前2頁,即使是第二頁。 – JonH

+0

奧奇,謝謝你們! :顯示第0 - 29行(總計30個,查詢花了1.4580秒),我可以住這個 – Melvin

2

您需要在units.name上放置索引或唯一索引。

1

添加以下指標:

上unit.name和unit.id.的複合指數(覆蓋索引)
measurement.date和measurements.time的組合索引。
location.id上的索引

0

您應該嘗試在units.name上創建索引作爲第一步。但要明白,與索引之間存在折衷 - 讀取操作會更快,但會減慢寫入操作。如果您擔心這一點,或者您受到寫入緩慢的影響,那麼您可能需要嘗試在units.name中使用較少數量的字符創建索引。

例如,聲明對units.name的前12個字符的索引,你聲明以下:

CREATE INDEX first_twelve ON單元(名稱(12));

再說一遍,如果你沒有注意到只是拋出一個索引而產生的任何不良影響,這可能是沒有必要的,但是要記住這一點。

0
SELECT measurements.location_id, measurements.value, measurements.date, measurements.time, locations.name, locations.lat, locations.lng 
FROM measurements 
LEFT JOIN units ON units.id = measurements.unit_id 
LEFT JOIN locations ON locations.id = measurements.location_id 
WHERE units.id = 4 
GROUP BY measurements.location_id 
ORDER BY measurements.date DESC, measurements.time DESC 
+0

謝謝,它速度更快,但顯示來自ASC的「測量」記錄,我想要最新的記錄。需要在團隊之前發生的順序。我不知道這是如何工作的。這個查詢我實際上第一次。 – Melvin

+0

@Melvin可能會更快地在where子句中有一個子查詢。 '日期=選擇最大日期'。那麼你可以擺脫你的分組和排序。在一個日期時間字段中獲取日期和時間也會更快,但這是另一回事。 – dqhendricks