У меня есть схема БД как таковая,
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
-- -----------------------------------------------------
-- Schema stack_vista
-- -----------------------------------------------------
-- -----------------------------------------------------
-- Schema stack_vista
-- -----------------------------------------------------
CREATE SCHEMA IF NOT EXISTS `stack_vista` DEFAULT CHARACTER SET utf8 ;
USE `stack_vista` ;
-- -----------------------------------------------------
-- Table `stack_vista`.`csv`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `stack_vista`.`csv` (
`idcsv` INT NOT NULL AUTO_INCREMENT,
`serviceCode` VARCHAR(45) NULL,
`offerDate` DATETIME NULL,
`price` VARCHAR(45) NULL,
`offerDuration` INT NULL,
`occupancy` INT NULL,
`extra_cols` VARCHAR(45) NULL,
PRIMARY KEY (`idcsv`),
INDEX `index_service_code` (`serviceCode` ASC))
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `stack_vista`.`offers`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `stack_vista`.`offers` (
`idoffers` INT NOT NULL AUTO_INCREMENT,
`shipSlug` VARCHAR(45) NULL,
`offerLink` VARCHAR(45) NULL,
`name` VARCHAR(45) NULL,
`serviceCode` VARCHAR(45) NULL,
`extra_cols` VARCHAR(45) NULL,
PRIMARY KEY (`idoffers`),
INDEX `index_offer_code` (`serviceCode` ASC),
FULLTEXT INDEX `index_ship_slug` (`shipSlug` ASC))
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `stack_vista`.`ships`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `stack_vista`.`ships` (
`idships` INT NOT NULL AUTO_INCREMENT,
`slug` VARCHAR(45) NULL,
`name` VARCHAR(45) NULL,
PRIMARY KEY (`idships`),
FULLTEXT INDEX `index_slug` (`slug` ASC))
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `stack_vista`.`props`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `stack_vista`.`props` (
`idprops` INT NOT NULL AUTO_INCREMENT,
`idoffers` INT NOT NULL,
`propName` VARCHAR(45) NULL,
`propCode` VARCHAR(45) NULL,
`type` VARCHAR(45) NULL,
PRIMARY KEY (`idprops`),
INDEX `fk_props_offers_idx` (`idoffers` ASC),
INDEX `index_type` (`type` ASC),
CONSTRAINT `fk_props_offers`
FOREIGN KEY (`idoffers`)
REFERENCES `stack_vista`.`offers` (`idoffers`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `stack_vista`.`location`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `stack_vista`.`location` (
`idlocation` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(45) NULL,
`code` VARCHAR(45) NULL,
`type` VARCHAR(45) NULL,
PRIMARY KEY (`idlocation`),
INDEX `index_type` (`type` ASC),
INDEX `index_name` (`name` ASC))
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `stack_vista`.`offers_has_location`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `stack_vista`.`offers_has_location` (
`offers_idoffers` INT NOT NULL,
`location_idlocation` INT NOT NULL,
PRIMARY KEY (`offers_idoffers`, `location_idlocation`),
INDEX `fk_offers_has_location_location1_idx` (`location_idlocation` ASC),
INDEX `fk_offers_has_location_offers1_idx` (`offers_idoffers` ASC),
CONSTRAINT `fk_offers_has_location_offers1`
FOREIGN KEY (`offers_idoffers`)
REFERENCES `stack_vista`.`offers` (`idoffers`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_offers_has_location_location1`
FOREIGN KEY (`location_idlocation`)
REFERENCES `stack_vista`.`location` (`idlocation`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
Моя таблица csv
- это таблица, в которую я добавляю данные, импортированные из csv, и предлагает предложения для разных услуг / поездок, для разных дат, местоположенияи типы. Он может иметь 10000-100000 записей, около 900-1000 сервисов и их комбинацию, как видно из group by
.
Различные сервисы отображаются в servicCode
из таблицы offers
, которая уникальна в offers
таблица.
Некоторые из offers
имеют shipSlugs
, что соответствует slugs
в таблице ships
.
Я пытаюсь перечислить все возможные serviceCodes
offerDate
, propTypeId
и shipSlug
. Так как существуют другие факторы, например, csv.extra_cols
и csv.offerDuration
, которые влияют на цену, я просто хотел получить MIN(Price)
на основе столбцов, используемых в GROUP BY
, следовательно, агрегации.
Iдобавили индекс в каждый столбец, который включается либо в условие where, либо в условия объединения.
Мой запрос, указанный ниже, в настоящее время занимает от 6 до 9 секунд. Что еще можно сделать для оптимизации этого запроса:
SELECT
i.serviceCode AS serviceCode,
i.offerDate AS offerDate,
MIN(i.price) AS price,
i.offerDuration AS duration,
i.occupancy AS occupancy,
p.idprops AS propTypeId,
p.propName AS propTypeName,
p.propCode AS propTypeCode,
p.type AS type,
g.idlocation AS destinationId,
g.name AS destinationName,
g.code AS destinationCode,
g.type AS destinationType,
o.idoffers AS offerId,
o.offerlink AS offerlink,
o.name AS name,
o.shipSlug AS shipSlug,
s.name AS shipName,
CONCAT_WS('-',
YEAR(i.offerDate),
MONTH(i.offerDate)) AS offer_year_month_date
FROM
csv i
JOIN
offers o ON o.serviceCode = i.serviceCode
LEFT JOIN
ships s ON o.shipSlug = s.slug
JOIN
props p ON o.idoffers = p.idoffers
JOIN
offers_has_location og ON o.idoffers = og.offers_idoffers
JOIN
location g ON g.idlocation = og.location_idlocation
WHERE
p.type = 'travelType'
AND g.code IN ('Earth' , 'River', 'HighLands')
GROUP BY serviceCode, offer_year_month_date, propTypeId, shipSlug;