From 63412dc25622d2eeb9a8561e1a72fb5737dfed18 Mon Sep 17 00:00:00 2001 From: Kentaro Ohkouchi Date: Mon, 5 Aug 2019 19:35:57 +0900 Subject: [PATCH] =?UTF-8?q?=E5=95=86=E5=93=81=E4=B8=80=E8=A6=A7,=20?= =?UTF-8?q?=E5=95=86=E5=93=81=E8=A9=B3=E7=B4=B0=E3=81=AE=E3=83=91=E3=83=95?= =?UTF-8?q?=E3=82=A9=E3=83=BC=E3=83=9E=E3=83=B3=E3=82=B9=E6=94=B9=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - dtb_products_class を full scan していたのを product_id で index scan するよう修正 - PostgreSQL/MySQL で同一クエリを使用するよう修正 --- data/class/SC_Product.php | 25 +++++++---- data/class/db/SC_DB_DBFactory.php | 18 ++++++-- .../db/dbfactory/SC_DB_DBFactory_PGSQL.php | 44 ------------------- 3 files changed, 32 insertions(+), 55 deletions(-) diff --git a/data/class/SC_Product.php b/data/class/SC_Product.php index 7206e138ee..1242ba3c08 100644 --- a/data/class/SC_Product.php +++ b/data/class/SC_Product.php @@ -116,9 +116,10 @@ public function findProductCount(&$objQuery, $arrVal = array()) * の配列を取得する. * * @param SC_Query $objQuery SC_Query インスタンス + * @param array $product_ids 商品IDの配列 * @return array 商品一覧の配列 */ - public function lists(&$objQuery) + public function lists(&$objQuery, $product_ids = array()) { $col = <<< __EOS__ product_id @@ -144,7 +145,7 @@ public function lists(&$objQuery) ,del_flg ,update_date __EOS__; - $res = $objQuery->select($col, $this->alldtlSQL()); + $res = $objQuery->select($col, $this->alldtlSQL('', $product_ids)); return $res; } @@ -169,8 +170,13 @@ public function getListByProductIds(&$objQuery, $arrProductId = array()) $where = 'alldtl.product_id IN (' . SC_Utils_Ex::repeatStrWithSeparator('?', count($arrProductId)) . ')'; $where .= ' AND alldtl.del_flg = 0'; - $objQuery->setWhere($where, $arrProductId); - $arrProducts = $this->lists($objQuery); + $objQuery->setWhere( + $where, + // SC_DB_DBFactory::alldtlSQL() で生成される追加条件のため + // product_id の配列を生成ておく + array_merge($arrProductId, $arrProductId, $arrProductId) + ); + $arrProducts = $this->lists($objQuery, $arrProductId); // 配列のキーを商品IDに $arrProducts = SC_Utils_Ex::makeArrayIDToKey('product_id', $arrProducts); @@ -201,9 +207,11 @@ public function getDetail($product_id) { $objQuery = SC_Query_Ex::getSingletonInstance(); - $from = $this->alldtlSQL(); + $from = $this->alldtlSQL('', array($product_id)); $where = 'product_id = ?'; - $arrWhereVal = array($product_id); + // SC_DB_DBFactory::alldtlSQL() で生成される追加条件のため + // product_id の配列を生成ておく + $arrWhereVal = array($product_id, $product_id, $product_id); $arrProduct = (array)$objQuery->getRow('*', $from, $where, $arrWhereVal); // 税込金額を設定する @@ -621,13 +629,14 @@ public static function setIncTaxToProduct(&$arrProduct) * 商品詳細の SQL を取得する. * * @param string $where_products_class 商品規格情報の WHERE 句 + * @param array $product_ids 商品IDの配列 * @return string 商品詳細の SQL */ - public function alldtlSQL($where_products_class = '') + public function alldtlSQL($where_products_class = '', $product_ids = array()) { $objDBFactory = SC_DB_DBFactory_Ex::getInstance(); - return $objDBFactory->alldtlSQL($where_products_class); + return $objDBFactory->alldtlSQL($where_products_class, $product_ids); } /** diff --git a/data/class/db/SC_DB_DBFactory.php b/data/class/db/SC_DB_DBFactory.php index d60170ebd9..a1b7627c2d 100644 --- a/data/class/db/SC_DB_DBFactory.php +++ b/data/class/db/SC_DB_DBFactory.php @@ -241,13 +241,25 @@ function addLimitOffset($sql, $limit = 0, $offset = 0) * 商品詳細の SQL を取得する. * * @param string $where_products_class 商品規格情報の WHERE 句 + * @param array $product_ids 商品IDの配列 * @return string 商品詳細の SQL */ - public function alldtlSQL($where_products_class = '') + public function alldtlSQL($where_products_class = '', $product_ids = array()) { if (!SC_Utils_Ex::isBlank($where_products_class)) { $where_products_class = 'AND (' . $where_products_class . ')'; } + + $dtb_products_table = 'dtb_products'; + $product_id_cause = ''; + + // dtb_products_class の Full scan を防ぐため, + // 商品IDが特定できている場合は, 先に product_id で対象を絞り込む + if (count($product_ids) > 0) { + $in = SC_Utils_Ex::repeatStrWithSeparator('?', count($product_ids)); + $product_id_cause = ' AND product_id IN ('.$in.')'; + $dtb_products_table = ' ( SELECT * FROM dtb_products WHERE product_id IN ('.$in.') ) AS dtb_products'; + } /* * point_rate, deliv_fee は商品規格(dtb_products_class)ごとに保持しているが, * 商品(dtb_products)ごとの設定なので MAX のみを取得する. @@ -269,7 +281,7 @@ public function alldtlSQL($where_products_class = '') ,T4.point_rate ,T4.deliv_fee ,dtb_maker.name AS maker_name - FROM dtb_products + FROM $dtb_products_table INNER JOIN ( SELECT product_id ,MIN(product_code) AS product_code_min @@ -285,7 +297,7 @@ public function alldtlSQL($where_products_class = '') ,MAX(point_rate) AS point_rate ,MAX(deliv_fee) AS deliv_fee FROM dtb_products_class - WHERE del_flg = 0 $where_products_class + WHERE del_flg = 0 $where_products_class $product_id_cause GROUP BY product_id ) AS T4 ON dtb_products.product_id = T4.product_id diff --git a/data/class/db/dbfactory/SC_DB_DBFactory_PGSQL.php b/data/class/db/dbfactory/SC_DB_DBFactory_PGSQL.php index 2e411395d2..5bd81046c8 100644 --- a/data/class/db/dbfactory/SC_DB_DBFactory_PGSQL.php +++ b/data/class/db/dbfactory/SC_DB_DBFactory_PGSQL.php @@ -282,48 +282,4 @@ public function listTables(SC_Query &$objQuery) return $objQuery->getCol($col, $from, $where); } - - /** - * 商品詳細の SQL を取得する. - * - * PostgreSQL 用にチューニング。 - * @param string $where_products_class 商品規格情報の WHERE 句 - * @return string 商品詳細の SQL - */ - public function alldtlSQL($where_products_class = '') - { - if (!SC_Utils_Ex::isBlank($where_products_class)) { - $where_products_class = 'AND (' . $where_products_class . ')'; - } - /* - * point_rate, deliv_fee は商品規格(dtb_products_class)ごとに保持しているが, - * 商品(dtb_products)ごとの設定なので MAX のみを取得する. - */ - $sub_base = "FROM dtb_products_class WHERE del_flg = 0 AND product_id = dtb_products.product_id $where_products_class"; - $sql = <<< __EOS__ - ( - SELECT - dtb_products.* - ,dtb_maker.name AS maker_name - ,(SELECT MIN(product_code) $sub_base) AS product_code_min - ,(SELECT MAX(product_code) $sub_base) AS product_code_max - ,(SELECT MIN(price01) $sub_base) AS price01_min - ,(SELECT MAX(price01) $sub_base) AS price01_max - ,(SELECT MIN(price02) $sub_base) AS price02_min - ,(SELECT MAX(price02) $sub_base) AS price02_max - ,(SELECT MIN(stock) $sub_base) AS stock_min - ,(SELECT MAX(stock) $sub_base) AS stock_max - ,(SELECT MIN(stock_unlimited) $sub_base) AS stock_unlimited_min - ,(SELECT MAX(stock_unlimited) $sub_base) AS stock_unlimited_max - ,(SELECT MAX(point_rate) $sub_base) AS point_rate - ,(SELECT MAX(deliv_fee) $sub_base) AS deliv_fee - FROM dtb_products - LEFT JOIN dtb_maker - ON dtb_products.maker_id = dtb_maker.maker_id - WHERE EXISTS(SELECT * $sub_base) - ) AS alldtl -__EOS__; - - return $sql; - } }