加速复杂表上的查询(约100万行)

时间:2014-03-10 13:05:18

标签: php mysql sql query-optimization page-load-time

首先感谢您抽出时间阅读本文。

我正在处理一个处理以下数据的PHP Web应用程序,截至目前,在尝试检索数据时有明显的时间,特别是在深入查看选项时。现在的主要选项是VehicleType,Make,Model,Year,InternetPrice和Mileage。最终将使用更多的列。此列表中的其他列用于在整个页面中显示数据,因为在一个实例中显示10条记录。

表格结构:

CREATE TABLE `vehicles` (
  `id` int(12) NOT NULL AUTO_INCREMENT,
  `DealerID` int(6) DEFAULT NULL,
  `VIN` varchar(17) DEFAULT NULL,
  `StockNumber` varchar(10) DEFAULT NULL,
  `Status` varchar(1) DEFAULT NULL,
  `VehicleType` int(1) DEFAULT NULL,
  `Year` int(4) DEFAULT NULL,
  `Make` varchar(13) DEFAULT NULL,
  `Model` varchar(24) DEFAULT NULL,
  `Trim` varchar(35) DEFAULT NULL,
  `Body` varchar(25) DEFAULT NULL,
  `VehicleClass` varchar(50) DEFAULT NULL,
  `VehicleCategory` varchar(6) DEFAULT NULL,
  `Mileage` int(6) DEFAULT NULL,
  `Transmission` varchar(24) DEFAULT NULL,
  `EngineDisplacement` varchar(7) DEFAULT NULL,
  `EngineSize` varchar(15) DEFAULT NULL,
  `Induction` varchar(25) DEFAULT NULL,
  `DriveTrain` varchar(3) DEFAULT NULL,
  `FuelType` varchar(9) DEFAULT NULL,
  `FuelEconomyCity` int(2) DEFAULT NULL,
  `FuelEconomyHighway` int(2) DEFAULT NULL,
  `FuelEconomyCombined` int(1) DEFAULT NULL,
  `Doors` int(1) DEFAULT NULL,
  `OEMColorCodeExterior` varchar(10) DEFAULT NULL,
  `OEMColorCodeInterior` varchar(10) DEFAULT NULL,
  `OEMColorNameExterior` varchar(49) DEFAULT NULL,
  `OEMColorNameInterior` varchar(10) DEFAULT NULL,
  `GenericColorExterior` varchar(35) DEFAULT NULL,
  `GenericColorInterior` varchar(38) DEFAULT NULL,
  `InternetPrice` int(6) DEFAULT NULL,
  `ComparisonPrice` int(6) DEFAULT NULL,
  `WholeSalePrice` varchar(10) DEFAULT NULL,
  `MSRP` varchar(10) DEFAULT NULL,
  `InternetSpecial` varchar(1) DEFAULT NULL,
  `OemModelCode` varchar(12) DEFAULT NULL,
  `HasWarranty` varchar(1) DEFAULT NULL,
  `CertificationWarranty` int(3) DEFAULT NULL,
  `WarrantyMonth` int(1) DEFAULT NULL,
  `WarrantyMiles` int(1) DEFAULT NULL,
  `CertificationNumber` varchar(7) DEFAULT NULL,
  `ServiceContract` varchar(1) DEFAULT NULL,
  `InServiceDate` varchar(19) DEFAULT NULL,
  `CertificationDate` varchar(19) DEFAULT NULL,
  `DateManufactured` varchar(19) DEFAULT NULL,
  `DateCreated` varchar(19) DEFAULT NULL,
  `DateUpdated` varchar(19) DEFAULT NULL,
  `DateRemoved` varchar(19) DEFAULT NULL,
  `DatePhotosUpdated` varchar(19) DEFAULT NULL,
  `Photos` int(2) DEFAULT NULL,
  `SuperSizePhotos` int(2) DEFAULT NULL,
  `AddendumDetails` varchar(10) DEFAULT NULL,
  `DepartmentComments` varchar(239) DEFAULT NULL,
  `VehicleComments` varchar(1987) DEFAULT NULL,
  `Options` varchar(2264) DEFAULT NULL,
  `PurchasePayment` decimal(5,2) DEFAULT NULL,
  `PurchaseDownPayment` decimal(6,2) DEFAULT NULL,
  `PurchaseTerm` int(2) DEFAULT NULL,
  `PurchaseDisclosure` varchar(10) DEFAULT NULL,
  `PurchaseRate` decimal(3,2) DEFAULT NULL,
  `LeasePayment` decimal(2,2) DEFAULT NULL,
  `LeaseDownPayment` decimal(2,2) DEFAULT NULL,
  `LeaseTerm` int(1) DEFAULT NULL,
  `LeaseDisclosure` varchar(10) DEFAULT NULL,
  `LeaseRate` decimal(2,2) DEFAULT NULL,
  `LeaseResidual` decimal(2,2) DEFAULT NULL,
  `Reserved1` varchar(10) DEFAULT NULL,
  `Reserved2` varchar(10) DEFAULT NULL,
  `Reserved3` varchar(10) DEFAULT NULL,
  `Reserved4` varchar(10) DEFAULT NULL,
  `Reserved5` varchar(10) DEFAULT NULL,
  `Reserved6` varchar(10) DEFAULT NULL,
  `sitecert` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `VIN` (`VIN`),
  KEY `Make` (`Make`),
  KEY `StockNumber` (`StockNumber`),
  KEY `Model` (`Model`),
  KEY `Trim` (`Trim`),
  KEY `Body` (`Body`),
  KEY `VehicleClass` (`VehicleClass`),
  KEY `Transmission` (`Transmission`),
  KEY `DealerID` (`DealerID`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=46527428 ;

一个示例查询:

SELECT *
FROM vehicles
WHERE Make = 'Audi'
    AND VehicleType = '0'
    AND Model = 'A4'
    AND InternetPrice BETWEEN 0 AND 999999
    AND Year BETWEEN 1983 AND 2015
    AND Mileage > 0
    AND DealerID IN ('AA'
        ,'156553'
        ,'229602'
        ,'160483'
        ,'2953'
        ,'161712'
        ,'228576'
        ,'228921'
        ,'7590'
        ,'20813'
        ,'158105'
        ,'160286'
        ,'164479'
        ,'164487'
        ,'182543'
        ,'158860'
        ,'186479'
        ,'227170'
        ,'226327'
        )
ORDER BY sitecert DESC
    ,InternetPrice DESC 
LIMIT 0, 10

有人会有任何建议来优化此查询或表吗?当然,整个页面中还有其他代码,但我已经将它计时到导致延迟的查询。

感谢您的帮助!

更新:

MySQL解释:

id select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  vehicles    ref Make,Model,DealerID Model   75  const   1675    Using where; Using filesort

年份更新为INT

3 个答案:

答案 0 :(得分:0)

根据您的数据库,您应该在以下字段中添加索引:

Make
VehicleType
Model
InternetPrice
Year
Mileage
DealerId

年份应为DATE类型,而不是文本(INT也有意义)。

这可以解决您的问题。

答案 1 :(得分:0)

我的建议:

  • 使用组制作
  • 对您的表进行分区,列可能有用(make,Year)
  • 将您的表存储在inndb引擎而不是myisam中并构建您的 自我一些聚集索引来参加你的谓词!

答案 2 :(得分:-1)

对于这种情况,您必须阅读EXPLAIN结果并相应地调整索引。

然而,只有1600行排序我根本不会打扰。如果你仍然想让它更快,你似乎需要一个组合键,包括一个Model和一个sitecert后跟价格,两者都是相反的顺序。

表示您必须有两个额外的列,其中存储了sitecert和price的负值。然后在(Model,nsitecert,nInternetPrice)上添加一个索引,并在没有DESC的情况下命令消除文件分区

如果您的搜索查询不涉及任何模型但任何参数组合 - 那么就应该考虑像Sphinx Search这样的外部搜索引擎了。