2

我有一个规范化的数据库结构,我将尝试解释。

3张桌子:

  • 简介
  • 关键词
  • 关键字配置文件

我网站上的每个个人资料都可以链接到不同数量的关键字。每个关键字在关键字表中都有一个 ID 号。每个配置文件在配置文件表中都有一个 ID 号。keyword_profile 表有大约 600k 行,keywordID 链接到 profileID。

我在配置文件表中的 ID 列上有一个 PRIMARY 索引。
我在关键字表中的 ID 列上有一个 PRIMARY 索引。
我在关键字表中的关键字名称列上有一个唯一索引。
我在keyword_profile 表上有一个PRIMARY 索引,如下所示:(profile_id,keyword_id)
我在keyword_profile 表的profile_ID 列上有一个索引

下一步:当我执行以下查询时(特定关键字名为“dienst”):

EXPLAIN SELECT profiles.hoofdrubriek, profiles.plaats, profiles.bedrijfsnaam, profiles.gemeente, profiles.bedrijfsslogan, profiles.straatnaam, profiles.huisnummer, profiles.postcode, profiles.telefoonnummer, profiles.fax,profiles.email, profiles.website, profiles.bedrijfslogo
FROM profiles
INNER JOIN profile_dienst ON profiles.ID = profile_dienst.profile_id
INNER JOIN diensten ON profile_dienst.dienst_id = diensten.ID
WHERE (
diensten.dienst = 'Aannemersdiensten'
)
ORDER BY profiles.grade DESC , profiles.bedrijfsnaam

我得到以下结果。它扫描所有 600k 行!这并不是我真正希望的结果。我可以应用哪些索引,这样它就不会扫描整个表?

id - select_type - table - type - key - rows - Extra
1 - SIMPLE - diensten - const - dienst - 1 - Using temporary; Using filesort
1 - SIMPLE - profile_dienst - index - PRIMARY - 662000 - Using where; Using index
1 - SIMPLE - profiles - eq_ref - PRIMARY - 1 - Using where

谢谢你们的帮助!!

编辑:添加了 SHOW CREATE TABLE 结果:

CREATE TABLE `diensten` (
 `ID` mediumint(9) NOT NULL AUTO_INCREMENT,
 `dienst` varchar(255) NOT NULL,
 PRIMARY KEY (`ID`),
 UNIQUE KEY `dienst` (`dienst`)
) ENGINE=MyISAM AUTO_INCREMENT=1903 DEFAULT CHARSET=utf8


CREATE TABLE `profile_dienst` (
 `profile_id` varchar(20) NOT NULL,
 `dienst_id` varchar(20) NOT NULL,
 PRIMARY KEY (`dienst_id`,`profile_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8

CREATE TABLE `profiles` (
 `ID` varchar(255) NOT NULL DEFAULT '',
 `username` varchar(255) DEFAULT NULL,
...more columns...,
     `grade` int(5) NOT NULL,
     PRIMARY KEY (`ID`),
     KEY `IDX_TIMESTAMP` (`timestamp`),
     KEY `IDX_NIEUW` (`nieuw`),
     KEY `IDX_HOOFDRUBRIEK` (`hoofdrubriek`),
     KEY `bedrijfsnaam` (`bedrijfsnaam`),
     KEY `grade` (`grade`),
     KEY `gemeente` (`gemeente`),
     KEY `plaats` (`plaats`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8
4

2 回答 2

0

您需要更好地进行规范化..您正在加入一个带有 mediumint profile_dienst.dienst_id = diensten.ID 的 varrhar(20),这就是需要 FULL INDEX SCAN 的原因..这就是解释列类型:索引和额外:“使用索引" 表示.. MySQL 只能在数据类型相同的情况下使用索引

当 MySQL 可以使用索引时,带有内部自连接http://sqlfiddle.com/#!2/1ef09/4的小演示。使用了 INT、SMALLINT、CHAR 和 VARCHAR 数据类型。在这里你可以看到 JOIN ON 和 INT 和SMALLINT 也可以在 CHAR 和 VARCHAR 上使用索引和 JOIN .. 但是将 INT 与 CHAR 混合 MySQL 不能使用索引,需要进行 FULL 表扫描查看 TYPE: ALL

于 2013-11-01T22:02:57.647 回答
0

我认为这很好,它正在扫描所有的值,profile_dienst因为 MySql 必须寻找diensten.ID. 好消息是使用和索引。

您可以在此处查看有关 MySql 解释计划的 Extra 列的更多信息:EXPLAIN Extra Information

于 2013-10-25T11:01:44.183 回答