如何减少mysql查询运行时间

如何减少mysql查询运行时间,mysql,Mysql,这是我在网站的一个页面上运行的查询 SELECT DISTINCT b.CruisePortID, b.SailingDates, b.CruisePortID, b.ArriveTime, b.DepartTime, b.PortName, b.DayNumber FROM cruise_itineraries a, cruise_itinerary_days b, cruise_ports c WHERE a.

这是我在网站的一个页面上运行的查询

SELECT 
    DISTINCT b.CruisePortID,
    b.SailingDates,
    b.CruisePortID,
    b.ArriveTime,
    b.DepartTime,
    b.PortName,
    b.DayNumber
FROM
    cruise_itineraries a,
    cruise_itinerary_days b,
    cruise_ports c
WHERE
a.ID = b.CruiseItineraryID
AND a.CruisePortID = c.ID
AND a.ID = '352905'
AND b.CruisePortID != 0
GROUP BY b.DayNumber;
在phpmy admin中运行此查询需要3.20秒,因为巡航计划有30多万条记录 我也尝试了索引,索引后显示2.92秒。是否有可能将查询时间缩短到0.10秒以下。这有助于提高我的网站性能

这里是详细信息

 CREATE TABLE IF NOT EXISTS `cruise_itineraries` (
  `cl` int(11) NOT NULL,
  `ID` bigint(20) NOT NULL,
  `Description` varchar(500) NOT NULL,
  `SailingPlanID` varchar(100) NOT NULL,
  `VendorID` varchar(100) NOT NULL,
  `VendorName` varchar(100) NOT NULL,
  `ShipID` varchar(100) NOT NULL,
  `ShipName` varchar(100) NOT NULL,
  `Duration` int(11) NOT NULL,
  `DestinationID` varchar(100) NOT NULL,
  `Date` datetime NOT NULL,
  `CruisePortID` varchar(100) NOT NULL,
  `TradeRestriction` varchar(100) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE IF NOT EXISTS `cruise_itinerary_days` (
  `cld` int(11) NOT NULL,
  `CruiseItineraryID` varchar(100) NOT NULL,
  `SailingDates` datetime NOT NULL,
  `VendorID` int(11) NOT NULL,
  `VendorName` varchar(100) NOT NULL,
  `ShipID` int(11) NOT NULL,
  `ShipName` varchar(100) NOT NULL,
  `SailingPlanID` int(11) NOT NULL,
  `PlanName` varchar(100) NOT NULL,
  `DayNumber` bigint(20) NOT NULL,
  `PortName` varchar(100) NOT NULL,
  `CruisePortID` varchar(100) NOT NULL,
  `ArriveTime` varchar(100) NOT NULL,
  `DepartTime` varchar(100) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE IF NOT EXISTS `cruise_ports` (
  `cp` int(11) NOT NULL,
  `ID` varchar(100) NOT NULL,
  `Name` varchar(100) NOT NULL,
  `Description` varchar(1000) NOT NULL,
  `NearestAirportCode` varchar(100) NOT NULL,
  `UNCode` varchar(100) NOT NULL,
  `Address` varchar(500) NOT NULL,
  `City` varchar(100) NOT NULL,
  `StateCode` varchar(100) NOT NULL,
  `CountryCode` varchar(100) NOT NULL,
  `PostalCode` varchar(100) NOT NULL,
  `Phone` varchar(50) NOT NULL,
  `Fax` varchar(100) NOT NULL,
  `Directions` varchar(1000) NOT NULL,
  `Content` varchar(1000) NOT NULL,
  `HomePageURL` varchar(100) NOT NULL,
  `Longitude` varchar(100) NOT NULL,
  `Latitude` varchar(500) NOT NULL,
  `CarnivalID` varchar(100) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


    ALTER TABLE `cruise_itineraries`
  ADD PRIMARY KEY (`cl`),
  ADD KEY `ID_2` (`ID`);

    ALTER TABLE `cruise_itineraries`
  ADD PRIMARY KEY (`cl`),
  ADD KEY `ID_2` (`ID`);


ALTER TABLE `cruise_itinerary_days`
  ADD PRIMARY KEY (`cld`);

ALTER TABLE `cruise_ports`
  ADD PRIMARY KEY (`cp`);


ALTER TABLE `cruise_itineraries`
  MODIFY `cl` int(11) NOT NULL AUTO_INCREMENT;

ALTER TABLE `cruise_itinerary_days`
  MODIFY `cld` int(11) NOT NULL AUTO_INCREMENT;

ALTER TABLE `cruise_ports`
  MODIFY `cp` int(11) NOT NULL AUTO_INCREMENT;
解释结果:

+----+-------------+-------+------+---------------+------+---------+-------+---------+--------------------------------------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref   | rows    | Extra                                                  |
+----+-------------+-------+------+---------------+------+---------+-------+---------+--------------------------------------------------------+
|  1 | SIMPLE      | a     | ref  | ID_2          | ID_2 | 8       | const |       1 | Using index condition; Using temporary; Using filesort |
|  1 | SIMPLE      | c     | ALL  | NULL          | NULL | NULL    | NULL  |    3267 | Using where; Using join buffer (Block Nested Loop)     |
|  1 | SIMPLE      | b     | ALL  | NULL          | NULL | NULL    | NULL  | 2008191 | Using where; Using join buffer (Block Nested Loop)     |
+----+-------------+-------+------+---------------+------+---------+-------+---------+--------------------------------------------------------+

+----+-------------+-------+------+------------------------------------+------------------------------------+---------+-------+------+--------------------------------------------------------------+
| id | select_type | table | type | possible_keys                      | key                                | key_len | ref   | rows | Extra                                                        |
+----+-------------+-------+------+------------------------------------+------------------------------------+---------+-------+------+--------------------------------------------------------------+
|  1 | SIMPLE      | b     | ref  | Idx_CruiseItineraryID_CruisePortID | Idx_CruiseItineraryID_CruisePortID | 9       | const |   12 | Using index condition; Using temporary; Using filesort       |
|  1 | SIMPLE      | a     | ref  | ID_2                               | ID_2                               | 8       | const |    1 | Distinct                                                     |
|  1 | SIMPLE      | c     | ALL  | NULL                               | NULL                               | NULL    | NULL  | 3267 | Using where; Distinct; Using join buffer (Block Nested Loop) |
+----+-------------+-------+------+------------------------------------+------------------------------------+---------+-------+------+--------------------------------------------------------------+

首先,我想声明,尽量避免隐式MySQL连接。 改为使用内部联接

我个人认为内部连接更好,因为它更简单 可读的。它更好地显示了表格之间的关系。你有 连接中的这些关系,并在何处进行过滤 条款这种分离使查询更具可读性

我发现的缺点是:

  • 邮轮行程.ID的数据类型为BIGINT,而邮轮行程.cruiseIneraryid的数据类型为varchar。但您在查询中匹配了它们。因此,无论您在巡航行程天数上使用索引,它都会运行缓慢

    将cruise\u Tinerary\u days.CruiseIneraryId的数据类型更改为BIGINT

    ALTER TABLE cruise\u internative\u days修改cruiseIneraryID BIGINT

  • 接下来,您必须根据查询在cruise\u Cinerary\u days表上创建一个复合索引

    ALTER TABLE cruise\u international\u days添加索引Idx\u cruiseIneraryID\u CruisePortID
    cruiseIneraryID
    CruisePortID
    )`

  • 现在在cruise_ports.ID字段的cruise_ports表中创建索引

    更改表格
    cruise\u port
    添加索引
    Idx\u cruise\u port\u ID
    ID

最后,查询是使用内部联接来表示的,因为我已经说明了上述选择背后的原因:

SELECT 
    DISTINCT b.CruisePortID,
    b.SailingDates,
    b.CruisePortID,
    b.ArriveTime,
    b.DepartTime,
    b.PortName,
    b.DayNumber
FROM cruise_itineraries a
INNER JOIN cruise_itinerary_days b ON a.ID = b.CruiseItineraryID
INNER JOIN cruise_ports c ON a.CruisePortID = c.ID
WHERE a.ID = 352905
AND b.CruisePortID != 0
GROUP BY b.DayNumber;

发布所有相关的表结构。我的意思是创建表代码。意思是您想要这些表的数据结构,对吗?还要说明您在tablescreate表语句中有哪些索引示例:
create table MyGuests(id INT(6)无符号自动递增主键,firstname VARCHAR(30)不为NULL,lastname VARCHAR(30)不为NULL,email VARCHAR(50),regu date TIMESTAMP)
正如您所看到的,cruise\u Tinerary\u days表中的扫描行数非常多!!谢谢你的建议。我将实现并与您共享结果。请共享此查询的解释结果。听起来很棒@vigneshrajkumar
cruise\u ports
needs
INDEX(ID)
。如果答案适合您,请练习将其标记为已接受。让别人觉得它有用@维涅斯拉伊库马尔