2017-09-25 78 views
2

我遇到的性能问题太大了。我使用PHP脚本从数据库中获取数据并将其插入到另一个表中(该脚本仅在数据库上运行查询,后者粘贴到下一个数据以获取数据,然后INSERT)。有两个表需要加入并输出结果(填写第三个表),但其中一个表有3.9M行数据,第二个表有416k行。问题是我必须在类型varchar上使用连接,因为这些表没有以任何方式连接(通过列“name”连接),因为它是它们唯一共同的列。该表的结构是这样的:大型表上的MySQL查询性能问题

TABLE streets 
    id (PK, int), 
    name varchar(70), 
    postnrid (FK, int) 

    TABLE csvstreets 
    id (PK, int), 
    lat decimal(12,10), 
    lng decimal(12,10), 
    streetname varchar(70) 

表的街道是一个有390万行的查询如下所示:

SELECT s.id, c.lat, c.lng FROM streets AS s JOIN csvstreets AS c ON LOWER(s.name) = LOWER(c.streetname) 

查询正在运行2天直了,它没”完成,所以我不得不取消它。我已将两个表的“名称”列编入索引。在对查询做EXPLAIN它输出这样的:

# id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra 
'1', 'SIMPLE', 'c', 'ALL', NULL, NULL, NULL, NULL, '416240', '' 
'1', 'SIMPLE', 's', 'index', NULL, 'name', '73', NULL, '3890226', 'Using where; Using index; Using join buffer (flat, BNL join)' 

它看起来像“csvstreets”表不使用我为它所做的指数。我可以使用任何建议,因为我已经尝试了所有可以用来提高varchar连接性能的东西。 另外我不能限制结果输出,因为我需要所有返回的数据(约380k)。 我在脚本中添加了echo以查看它停止的位置,但它正在运行该查询2天的SELECT,从未得到INSERT部分。

+2

*我已收录既有“名”列( s.name)',同时发布解释您的查询计划 –

+0

感谢您的信息,“名称”列在字幕大小上有所不同,例如一条街道像“Balsta 300”,另一条是“balsta 301”,所以我必须使用LOWER()(或UPPER()w/e,它是一样的) – MirzaS

+4

您不需要使用lower()或upper(),除非您的归档以_cs(区分大小写)或二进制 – user1844933

回答

0

摆脱lower()s。它保持使用你的索引的连接,除非你设置了区分大小写的排序规则,你不需要它。当然没有必要将“Balsta 300”与“Balsta 301”区分开来。

如果以后你的查询还没有完成,显示所有的输出:两个表*它不是任何有用的多因'LOWER

show create table streets 
show create table csvstreets 
explain SELECT s.id, c.lat, c.lng FROM streets AS s JOIN csvstreets AS c ON s.name=c.streetname