2014-10-17 58 views
4

這是我在stackoverflow中的第一個問題,我很高興成爲這個社區的一員,因爲它幫了我很多次。MySQL - 非常簡單的加入時間太長

我不是SQL和MySQL的專家,但我正在一個需要大表(百萬行)的項目中工作。 我在加入時遇到問題,我不明白爲什麼需要這麼長時間。感謝提前:)

下面是表:

CREATE TABLE IF NOT EXISTS tabla_maestra(
id int UNIQUE, 
codigo_alta char(1), 
nombre varchar(100), 
empresa_apellido1 varchar(150), 
apellido2 varchar(50), 
tipo_via varchar(20), 
nombre_via varchar(100), 
numero_via varchar(50), 
codigo_via char(5), 
codigo_postal char(5), 
nombre_poblacion varchar(100), 
codigo_ine char(11), 
nombre_provincia varchar(50), 
telefono varchar(250) UNIQUE, 
actividad varchar(100), 
estado char(1), 
codigo_operadora char(3) 
); 

CREATE TABLE IF NOT EXISTS tabla_actividades_empresas(
empresa_apellido1 varchar(150), 
actividad varchar(100) 
); 

這裏是我想要做的查詢:

UPDATE tabla_maestra tm 
INNER JOIN tabla_actividades_empresas tae 
ON (tm.nombre!='' AND tae.empresa_apellido1=tm.empresa_apellido1) 
SET tm.actividad=tae.actividad; 

這個查詢的時間太長,並執行它之前,我是想以測試需要多長時間才能進行此簡單查詢:

SELECT COUNT(*) FROM tabla_maestra tm 
INNER JOIN tabla_actividades_empresas tae 
ON (tm.nombre!='' AND tae.empresa_apellido1=tm.empresa_apellido1); 

它仍然需要太長時間,爲什麼。下面是我用的指標:

CREATE INDEX cruce_nombre 
USING HASH 
ON tabla_maestra (nombre); 

CREATE INDEX cruce_empresa_apellido1 
USING HASH 
ON tabla_maestra (empresa_apellido1); 

CREATE INDEX index_actividades_empresas 
USING HASH 
ON tabla_actividades_empresas(empresa_apellido1); 

如果我使用EXPLAIN語句,這些結果如下:

http://oi59.tinypic.com/2zedoy0.jpg

我會如此感激收到任何答案,可以幫助我。非常感謝,丹妮。

+0

主鍵的缺失可能會導致緩慢的perforanace。 – 2014-10-17 13:57:11

回答

1

包含五十萬行的連接 - 如查詢計劃所示 - 必然需要一些時間。 count(*)查詢更快,因爲它不需要讀取tabla_maestra表本身,但仍需要掃描索引cruce_empresa_apellido1的所有行。

它可以幫助一些,如果你做指數index_actividades_empresas一個唯一指數(假設這確實是合適的),或者相反,如果你丟棄的索引,將列empresa_apellido1tabla_actividades_empresas的主鍵。

如果即使這樣也不能提供足夠的性能,那麼我唯一要做的其他事情就是給表tabla_actividades_empresas一個整數類型的合成主鍵,並將tabla_maestra的相應列更改爲匹配。這應該有所幫助,因爲將整數與整數進行比較比將字符串與字符串進行比較要快,即使可以通過散列過濾(大部分)不匹配。

1

我同意其他人的看法(參見John Bollinger)關於它缺少主鍵的問題。它的ID很高(我注意到你擔心它會被重複,但是PK也能順利處理它 - 我的意思是MySQL的AUTOINCREMENT)。

爲什麼使用tabla_actividades_empresasempresa_apellido1而不是查找要引用的tabla_maestra的ID?

如果是這樣,你可以定義外鍵:tabla_actividades_empresasmaestra_id

因爲如果您將表與非字符串類型相關聯會更好。

您也可以在它們之間的JOIN操作之前子查詢這些表。這是一個例子:

UPDATE (SELECT * FROM tabla_maestra WHERE nombre != '') AS tm 
INNER JOIN tabla_actividades_empresas AS tae 
ON tae.empresa_apellido1 = tm.empresa_apellido1 
SET tm.actividad = tae.actividad; 

我還沒有測試過它。但從那以後,它似乎是一個很好的行爲。

哦......每次你需要更新所有的數據行嗎?除非,你只能更新被遺忘者。您可以在LEFT JOIN之後應用UPDATEINNER JOIN以確定需要更新的項目。它有意義嗎?我不是任何專家,但考慮一下可能很有用。

編輯

您可能也測試一些子查詢:

UPDATE tabla_maestra AS main, tabla_actividades_empresas AS aggr 
SET main.actividad = aggr.actividad 
WHERE main.empresa_apellido1 = aggr.empresa_apellido1 
AND main.nombre <> '' 

不要忘了嘗試調整的關係。

0

非常感謝你的回答。

事實是,表「tabla_maestra」是包含關於企業信息的表格,但開不包含對「ACTIVIDAD」場(企業活動)的值。此外,'id'字段仍然是空的(我將來會這樣做,很難解釋原因,但必須這樣做)。

我需要將每個企業的活動添加到包含每個企業名稱的活動的輔助表'tabla_actividades_empresas'中。我只需要做一次,不要再做了。然後,我將能夠刪除表'tabla_actividades_empresas',因爲我不需要它。

並且加入它們的唯一方法是通過字段'empresa_apellido1',這就是說,企業的名稱。

我已將該字段設爲'tabla_actividades_empresas.empresa_apellido1''唯一,但它不會提高性能。

而且它沒有意義的定義上的「tabla_actividades_empresas」的外鍵,因爲該領域「empresa_apellido1」只爲「tabla_actividades_empresas獨特的,而不是爲「tabla_maestra」(在這張表中,企業名稱可能會出現很多次,因爲企業可能在不同的地方有不同的辦公室)。也就是說'tabla_actividades_empresas'不包含重複企業,但'tabla_maestra'已重複名稱企業。

順便說一下,「調整關係」是什麼意思?我已經用explain語句嘗試過你的子查詢,並且它沒有正確使用索引,性能更差。