次のようなテーブルがあるとします。
テーブル名:CUSTOMER 主キー:CUSTOMER_ID + ------------- + --------------- + | CUSTOMER_ID | CUSTOMER_NAME | + ------------- + --------------- + | 1 | ビル| | 2 | トム| + ------------- + --------------- +
ここで、CUSTOMER_ATTRIBUTE
キーと値のペアを特定の値に結び付けることができるテーブルがあるとしCUSTOMER
ます。
テーブル名:CUSTOMER_ATTRIBUTE 主キー:(CUSTOMER_ID、ATTRIBUTE_TYPE_ID) + ------------- + ------------------- + --------------- --+ | CUSTOMER_ID | ATTRIBUTE_TYPE_ID | ATTRIBUTE_VALUE | + ------------- + ------------------- + --------------- --+ | 1 | FAVORITE_FOOD | ピザ| | 1 | FAVORITE_COLOR | ブルー| | 2 | FAVORITE_FOOD | タコス| | 2 | NAME_OF_PET | Fido | + ------------- + ------------------- + --------------- --+
ここで、考えられる属性のいくつかを使用して顧客を表すビューを作成するとします。
CREATE VIEW CUSTOMER_VIEW AS
SELECT
CUSTOMER.CUSTOMER_ID,
CUSTOMER.CUSTOMER_NAME,
FAVORITE_FOOD_ATTRIBUTE.ATTRIBUTE_VALUE AS FAVORITE_FOOD,
FAVORITE_COLOR_ATTRIBUTE.ATTRIBUTE_VALUE AS FAVORITE_COLOR
FROM
CUSTOMER
LEFT OUTER JOIN CUSTOMER_ATTRIBUTE favorite_food_attribute
ON customer.customer_id = favorite_food_attribute.customer_id
AND favorite_food_attribute.attribute_type_id = FAVORITE_FOOD
LEFT OUTER JOIN CUSTOMER_ATTRIBUTE favorite_color_attribute
ON customer.customer_id = favorite_color_attribute.customer_id
AND favorite_color_attribute.attribute_type_id = FAVORITE_COLOR
ここで、このビューをクエリするとします。
SELECT
CUSTOMER_ID,
CUSTOMER_NAME,
FAVORITE_COLOR
-- Notice: I did not ask for the FAVORITE_FOOD column
FROM
CUSTOMER_VIEW
Explainプランによると、Oracleはfavorite_food_attribute
、その値が不要であり、クエリのカーディナリティに影響を与えない場合でも(LEFT OUTER JOIN
テーブルの主キーを使用しているため)、まだ参加しています。
Oracleにこれらの不要な結合を回避させる方法はありますか?
更新:サンプルDDL
サンプルスキーマを作成するためのいくつかのDDLを次に示します。
CREATE TABLE CUSTOMER
(
CUSTOMER_ID NUMBER NOT NULL,
CUSTOMER_NAME VARCHAR2(100)
);
CREATE UNIQUE INDEX CUSTOMER_PK_INDEX
ON CUSTOMER(CUSTOMER_ID);
ALTER TABLE CUSTOMER
ADD CONSTRAINT CUSTOMER_PK
PRIMARY KEY (CUSTOMER_ID)
USING INDEX CUSTOMER_PK_INDEX;
CREATE TABLE CUSTOMER_ATTRIBUTE
(
CUSTOMER_ID NUMBER NOT NULL,
ATTRIBUTE_TYPE_ID NUMBER NOT NULL,
ATTRIBUTE_VALUE VARCHAR2(1000)
);
CREATE UNIQUE INDEX CUSTOMER_ATTRIBUTE_PK_INDEX
ON CUSTOMER_ATTRIBUTE(CUSTOMER_ID, ATTRIBUTE_TYPE_ID);
ALTER TABLE CUSTOMER_ATTRIBUTE
ADD CONSTRAINT CUSTOMER_ATTRIBUTE_PK
PRIMARY KEY (CUSTOMER_ID, ATTRIBUTE_TYPE_ID)
USING INDEX CUSTOMER_ATTRIBUTE_PK_INDEX;
CREATE OR REPLACE VIEW CUSTOMER_VIEW AS
SELECT
CUSTOMER.CUSTOMER_ID,
CUSTOMER.CUSTOMER_NAME,
favorite_food_attribute.attribute_value AS favorite_food,
favorite_color_attribute.attribute_value AS favorite_color
FROM
CUSTOMER
LEFT OUTER JOIN CUSTOMER_ATTRIBUTE favorite_food_attribute
ON customer.customer_id = favorite_food_attribute.customer_id
AND favorite_food_attribute.attribute_type_id = 5
LEFT OUTER JOIN CUSTOMER_ATTRIBUTE favorite_color_attribute
ON customer.customer_id = favorite_color_attribute.customer_id
AND favorite_color_attribute.attribute_type_id = 6;
ここで、このクエリでExplainプランを実行します。
SELECT CUSTOMER_ID FROM HFSMMM.CUSTOMER_VIEW
計画は次のとおりです。
SELECT STATEMENT、GOAL = ALL_ROWS Cost = 1 Cardinality = 1 Bytes = 65 ネストされたループの外側コスト=1カーディナリティ=1バイト=65 ネストされたループの外側コスト=1カーディナリティ=1バイト=39 INDEXFULLSCANオブジェクトの所有者=HFSMMMオブジェクト名=CUSTOMER_PK_INDEXコスト=1カーディナリティ=1バイト=13 INDEXUNIQUESCANオブジェクト所有者=HFSMMMオブジェクト名=CUSTOMER_ATTRIBUTE_PK_INDEXコスト=0カーディナリティ=1バイト=26 INDEXUNIQUESCANオブジェクト所有者=HFSMMMオブジェクト名=CUSTOMER_ATTRIBUTE_PK_INDEXコスト=0カーディナリティ=1バイト=26