缓慢的内部联接6桌

时间:2013-12-03 20:39:22

标签: mysql sql join

抱歉,我的SQL知识很业余。

SQL小提琴:http://sqlfiddle.com/#!2/5640d/1 请单击上面的链接以参考数据库结构和查询。

我有6个表,每个数据在每个表中只占一行,并且在所有6个表中我有3个相同的列CustgroupRandomNumberuser_id

Custgroup是一个群组名称,在群组中,每个数据都有唯一的RandomNumber

首次运行时查询非常慢(随机需要几秒到几分钟),之后会很快,但仅限前几页。如果我点击第20页或第30页,它将是非停止加载(刚刚花了大约5分钟)。而且数据不多,只有5000行,将来会遇到很大麻烦。我还没有添加任何WHERE子句,因为我需要对每列进行过滤在我的网站上。(不是我的想法,我的老板要求)。

我尝试将其更改为LEFT JOIN,JOIN以及我可以找到的任何其他方式,但加载速度仍然很慢。

我为所有表的user_id,Custgroup和RandomNumber添加了INDEX。 无论如何要解决这个问题?我从不擅长使用JOIN,对我的数据库来说真的很慢。

或者,如果我的桌子结构非常糟糕,请告诉我,我愿意重做它。

感谢。

**被修改

RUN EXPLAIN:

    id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra

    1   SIMPLE  tE  ALL     NULL    NULL    NULL    NULL    5685    

    1   SIMPLE  tA  ALL     NULL    NULL    NULL    NULL    6072    Using join buffer

    1   SIMPLE  t1  ref     user_id,Custgroup,RandomNumber  RandomNumber    23  func    1   Using where

    1   SIMPLE  tB  ALL     NULL    NULL    NULL    NULL    5868    Using where; Using join buffer

    1   SIMPLE  tC  ALL     NULL    NULL    NULL    NULL    6043    Using where; Using join buffer

    1   SIMPLE  tD  ALL     NULL    NULL    NULL    NULL    5906    Using where; Using join buffer


    Keyname Type    Unique  Packed  Column  Cardinality Collation   Null    Comment
    PRIMARY BTREE   Yes No  ID  6033    A       
    RandomNumber    BTREE   No  No  RandomNumber    6033    A       
    Custgroup   BTREE   No  No  Custgroup   1   A       
    user_id BTREE   No  No  user_id 1   A       

编辑:EXPLAIN EXTENDED .....

    id  select_type     table   type    possible_keys   key     key_len     ref     rows    filtered    Extra
    1   SIMPLE  tE  ALL     NULL    NULL    NULL    NULL    6084    100.00  
    1   SIMPLE  t1  ref     user_id,Custgroup,RandomNumber  RandomNumber    23  func    1   100.00  Using where
    1   SIMPLE  tB  ALL     NULL    NULL    NULL    NULL    5664    100.00  Using where; Using join buffer
    1   SIMPLE  tC  ALL     NULL    NULL    NULL    NULL    5976    100.00  Using where; Using join buffer
    1   SIMPLE  tA  ALL     NULL    NULL    NULL    NULL    6065    100.00  Using where; Using join buffer
    1   SIMPLE  tD  ALL     NULL    NULL    NULL    NULL    6286    100.00  Using where; Using join buffer

1 个答案:

答案 0 :(得分:3)

这种结构的逻辑索引必须是

CREATE INDEX UserAddedRecord1_ndx ON UserAddedRecord1 (user_id, Custgroup, RandomNumber);
CREATE INDEX UserAddedRecord1_A_ndx ON UserAddedRecord1_A (Custgroup, RandomNumber);
CREATE INDEX UserAddedRecord1_B_ndx ON UserAddedRecord1_B (Custgroup, RandomNumber);
CREATE INDEX UserAddedRecord1_C_ndx ON UserAddedRecord1_C (Custgroup, RandomNumber);
CREATE INDEX UserAddedRecord1_D_ndx ON UserAddedRecord1_D (Custgroup, RandomNumber);
CREATE INDEX UserAddedRecord1_E_ndx ON UserAddedRecord1_E (Custgroup, RandomNumber);

如果您要添加WHERE子句,他们应该在 JOIN条件之前进入相关索引(前提是您运行等于或{{1搜索,例如City =" New York")。例如,如果City位于UserAddedRecord1_B中,则UserAddedRecord1_B_ndx应为IN

但是在这一点上,我不得不问,为什么?显然,您始终为同一用户提供记录。例如:

City, Custgroup, RandomNumber

...很明显,你不能在这里拥有两个不同的用户(并且邮政编码与邮政编码在同一个区块中告诉我这不是真正意图作为一对多的关系)。

t1.Cell,t1.Name,t1.Gender,t1.Birthday
tA.Email,tA.State,tA.Address,tA.City,tA.Postcode

这些是单个大型用户信息表单的所有部分",分为(可选?)部分。

我猜测这种结构源于某种遗留/框架系统,它将表单提交部分映射到。这样某人可能在表B,C和E中有一个条目,在表A,C和D中有其他人。

如果这是真的,并且如果tB.Website,tB.Description, tC.Model,tC.Capital,tC.Registry,tC.NoEmployees, tD.SetUpDate,tD.PeopleInCharge,tD.Certification,tD.AddOEM, tD.NoResearcher,tD.RoomSize,tD.RegisterMessage, tE.WebsiteName,tE.OriginalWebsite,tE.QQ,tE.MSN,tE.Skype 对于所有表都相同,那么将此更快的一种方法是在user_id上明确添加条件每个表,并适当修改索引和JOIN:

user_id

尝试fiddle

要做的是将所有表合并到一个表中,并将所有字段放在一行中,然后,为了传统目的,您可以创建CREATE INDEX UserAddedRecord1_ndx ON UserAddedRecord1 (user_id, Custgroup, RandomNumber); CREATE INDEX UserAddedRecord1_A_ndx ON UserAddedRecord1_A (user_id, Custgroup, RandomNumber); CREATE INDEX UserAddedRecord1_B_ndx ON UserAddedRecord1_B (user_id, Custgroup, RandomNumber); CREATE INDEX UserAddedRecord1_C_ndx ON UserAddedRecord1_C (user_id, Custgroup, RandomNumber); CREATE INDEX UserAddedRecord1_D_ndx ON UserAddedRecord1_D (user_id, Custgroup, RandomNumber); CREATE INDEX UserAddedRecord1_E_ndx ON UserAddedRecord1_E (user_id, Custgroup, RandomNumber); ... FROM UserAddedRecord1 t1 JOIN UserAddedRecord1_A tA USING (user_id, CustGroup, RandomNumber) JOIN UserAddedRecord1_B tB USING (user_id, CustGroup, RandomNumber) JOIN UserAddedRecord1_C tC USING (user_id, CustGroup, RandomNumber) JOIN UserAddedRecord1_D tD USING (user_id, CustGroup, RandomNumber) JOIN UserAddedRecord1_E tE USING (user_id, CustGroup, RandomNumber) WHERE t1.user_id = '1' 看起来比如表1,A,B,C,D和E,每个都有一个"垂直"元组的分区。但是你会在包含所有字段的完整表格上运行的大VIEWs(并且你也可以保存在重复的列上)。