正确地将索引添加到大型数据库表

时间:2014-05-03 18:27:26

标签: mysql sql

问题是,在我向这些列中插入200.000-300.000行数据后,搜索移动得非常慢,我想到的第一件事是我可能没有正确添加的索引。我已经尝试添加尽可能多的BTREE索引phpmyadmin没有让我为所有添加。什么是我的表的正确索引?我有下表包含以下索引:

CREATE TABLE IF NOT EXISTS `carads` (
  `ADID` int(7) NOT NULL AUTO_INCREMENT,
  `LINK` varchar(255) CHARACTER SET latin1 NOT NULL,
  `TITLE` varchar(255) NOT NULL,
  `MAKE` varchar(50) CHARACTER SET latin1 NOT NULL,
  `MODEL` varchar(100) CHARACTER SET latin1 NOT NULL,
  `FUEL` varchar(50) CHARACTER SET latin1 NOT NULL,
  `LOC` varchar(100) NOT NULL,
  `TRANS` varchar(50) NOT NULL,
  `YEAR` varchar(4) CHARACTER SET latin1 NOT NULL,
  `BODY` varchar(255) CHARACTER SET latin1 NOT NULL,
  `DESCRIPT` text CHARACTER SET latin1 NOT NULL,
  `PHONENR` varchar(20) NOT NULL,
  `MILEAGE` int(11) NOT NULL,
  `PRICE` int(20) NOT NULL,
  `DISTANCE` int(250) NOT NULL,
  `POSTCODE` varchar(250) NOT NULL,
  `IMAGE1` varchar(255) NOT NULL,
  `IMAGE2` varchar(255) NOT NULL,
  `IMAGE3` varchar(255) NOT NULL,
  `IMAGE4` varchar(255) NOT NULL,
  `IMAGE5` varchar(255) NOT NULL,
  `CPHONE` varchar(250) NOT NULL,
  `CEMAIL` varchar(500) NOT NULL,
  `COLOUR` varchar(250) NOT NULL,
  `EQUIPMENT` text NOT NULL,
  `STATUS` tinyint(1) NOT NULL DEFAULT '1',
  `DATE` date NOT NULL,
  `DEL` int(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`ADID`),
  KEY `ix_MakeModelPrice` (`STATUS`,`MAKE`(25),`MODEL`(25),`PRICE`),
  KEY `ix_Price` (`PRICE`,`STATUS`,`DEL`,`TITLE`(30),`ADID`),
  KEY `ix_Date` (`DATE`,`STATUS`,`DEL`,`TITLE`(30),`ADID`),
  KEY `LINK` (`LINK`),
  FULLTEXT KEY `MODEL` (`MODEL`),
  FULLTEXT KEY `SearchIndex`  (`TITLE`,`LOC`,`TRANS`,`CPHONE`,`CEMAIL`,`COLOUR`,`EQUIPMENT`),
  FULLTEXT KEY `MAKE` (`MAKE`)
) 
ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=2478687;

1 个答案:

答案 0 :(得分:1)

这很复杂,我们无法给你正确的答案,你必须自己理解并找到最佳答案。

你必须牢记以下:

  1. 查询优化器将只选择一个索引。
  2. 以“status”和“del”(布尔值或95%的行具有所选值的值)开头的索引不会添加任何值,除了经常查询这些虚拟列之后,高度选择性的价值观。
  3. 您应该首先找到属于

    的属性
    • 填写了大部分查询(我可以想象“make”,“price”和“year”都是不错的候选人)
    • 是最具选择性的(意味着产生的行<10%)

    您必须找出表格中存在的每个列的值分布。例子:

    请:

    • 宝马:5%
    • 阿尔法罗密欧:1%
    • 大众:7%
    • ...

    价格-范围:

    • 0..999:3%
    • 1000..1999:4%
    • 2000..3000:5%
    • ...

    如果所有搜索中有80%包含“make”,“price”和“year”,则创建一个包含所有3列的索引。将大多数搜索中最具选择性和/或提及的列放在前面,然后是其他列。

    运气好的话,你可以大大改善许多搜索的响应时间。然后,您可以深入挖掘统计数据并添加其他一些索引。也许80%的搜索都选择了“make”,但其余的仍然有很多没有“make”的搜索,但是关注“price”和“fuel”,然后为这些搜索创建索引。

    当您使用“代码”(例如Alfa Romeo = 1,BMW = 2,VW = 3,...)或群集值范围(例如price_range:0..999,1000)时,您也可以提高性能。 .2000,...)。这可以帮助MySQL构建更高效的索引(更小的内存占用更少,I / 0更少)。

    要更好地理解索引,请尝试提交这样的查询(我希望使用索引ix_MakeModelPrice):

    -- ix_MakeModelPrice: STATUS`,`MAKE`(25),`MODEL`(25),`PRICE`
    
    SELECT * FROM carads
        where STATUS=1 AND MAKE='Alfa Romeo' 
          AND MODEL='159' and PRICE BETWEEN 100 and 1000
        order by ADID Desc
        LIMIT 0
    

    此查询应该很快(希望有一些匹配的行)。你明白为什么它快吗? “STATUS”不是选择性的,但其余的应该减少索引扫描发现的行数可能低于1%。物理读取(行)的数量减少到最小值=&gt;更快的反应。