【问题标题】:Min, MAx SQL query optimization最小、最大 SQL 查询优化
【发布时间】:2018-07-28 15:04:25
【问题描述】:

我有以下查询,我真的需要帮助优化它:

SELECT min(p.price) as min_price, max(p.price) as max_price
FROM product p
INNER JOIN product_category pc
    ON p.id_product = pc.id_product AND
       p.id_project = 1 AND
       pc.id_category = 2 AND
       p.active = 1 

这些表格是:

CREATE TABLE `product` (
  `id_product` bigint(10) UNSIGNED NOT NULL,
  `id_project` int(11) NOT NULL,
  `reference` varchar(50) NOT NULL,
  `reference_internal` varchar(125) NOT NULL,
  `sku` varchar(50) NOT NULL,
  `price` float(12,2) NOT NULL,
  `old_price` float NOT NULL,
  `reduction_amount` float NOT NULL,
  `reduction_percent` float NOT NULL,
  `is_reduced` int(1) NOT NULL,
  `id_manufacturer` int(10) NOT NULL,
  `id_supplier` int(10) NOT NULL,
  `is_new` int(1) NOT NULL,
  `popularity` int(1) NOT NULL,
  `quantity` int(1) NOT NULL,
  `active` int(1) NOT NULL,
  `date_add` datetime NOT NULL,
  `date_upd` datetime NOT NULL,
  `id_category` int(11) NOT NULL,
  `indexed` int(1) NOT NULL,
  `id_color` int(13) NOT NULL,
  `rating` int(1) NOT NULL,
  `rating_count` int(11) NOT NULL,
  `viewed` int(5) NOT NULL,
  `a_id_product` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `product`
  ADD PRIMARY KEY (`id_product`),
  ADD KEY `id_product` (`id_product`),
  ADD KEY `reference` (`reference`),
  ADD KEY `reference_internal` (`reference_internal`),
  ADD KEY `sku` (`sku`),
  ADD KEY `reduction_amount` (`reduction_amount`),
  ADD KEY `reduction_percent` (`reduction_percent`),
  ADD KEY `is_reduced` (`is_reduced`),
  ADD KEY `id_manufacturer` (`id_manufacturer`),
  ADD KEY `id_supplier` (`id_supplier`),
  ADD KEY `is_new` (`is_new`),
  ADD KEY `popularity` (`popularity`),
  ADD KEY `date_add` (`date_add`),
  ADD KEY `date_upd` (`date_upd`),
  ADD KEY `id_category` (`id_category`),
  ADD KEY `indexed` (`indexed`),
  ADD KEY `id_color` (`id_color`),
  ADD KEY `price` (`price`),
  ADD KEY `rating` (`rating`),
  ADD KEY `a_id_product` (`a_id_product`),
  ADD KEY `t7` (`price`,`id_product`,`id_project`,`active`) USING BTREE;
-- AUTO_INCREMENT for dumped tables
-- AUTO_INCREMENT for table `product`
ALTER TABLE `product`
  MODIFY `id_product` bigint(10) UNSIGNED NOT NULL AUTO_INCREMENT;
COMMIT;

有product_categories表:

CREATE TABLE `product_category` (
  `id_product` int(10) DEFAULT NULL,
  `id_project` int(11) NOT NULL,
  `id_category` int(5) NOT NULL,
  `menu_order` int(5) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- Indexes for dumped tables
--

--
-- Indexes for table `product_category`
--
ALTER TABLE `product_category`
  ADD KEY `id_product` (`id_product`),
  ADD KEY `id_project` (`id_project`),
  ADD KEY `id_category` (`id_category`),
  ADD KEY `menu_order` (`menu_order`),
  ADD KEY `t1` (`id_product`,`id_category`),
  ADD KEY `t2` (`id_product`,`id_project`,`id_category`);
COMMIT;

解释语句https://snag.gy/8ClFnh.jpg

我有 45 毫秒的执行时间,但数据库不是很大,我有大约 20.000 个产品,但当它上线时,我将拥有数百万个产品,0.0550 秒的执行时间对于这个数量的产品来说似乎很长,任何人都可以帮助优化建议?

我有 mysql 5.7。

【问题讨论】:

  • @Waayd 您是否建议 OP 只需要单个表上的索引?
  • 我不明白
  • "让索引表中的每一列"看看它是否有效是一个非常非常糟糕的主意。
  • product 表中的(id_project, active, price) 上的索引应该有帮助,至少可以加快查询的最大部分。不确定单个索引是否可以涵盖所有内容。
  • 乍一看,您的查询需要至少有这些“二级索引”索引product(id_product, active)product_category(id_product, id_category) 或覆盖索引product(id_product, active, price) ...但是因为 InnoDB 表引擎将 PRIMARY KEY 存储到二级索引,您可以从二级索引中删除 id_product 列..

标签: mysql sql


【解决方案1】:

如果您选择的行数很少(占总数的 0.5% 或更少),您的查询应该很容易优化。

下面的索引应该会有所帮助:

create index ix1_product on product (id_project, active, price);

create index ix2_procat on product_category (id_product, id_category);

【讨论】:

    猜你喜欢
    • 2012-01-30
    • 1970-01-01
    • 1970-01-01
    • 2015-10-24
    • 1970-01-01
    • 1970-01-01
    • 2014-08-06
    • 2012-05-03
    • 1970-01-01
    相关资源
    最近更新 更多