2016-11-26 5 views
0

私はMySQLデータベース設計のために、複数のバリアントスキーマを持つことができる製品に頭を下げています。大規模なデータセットのMySQLでのIFNULLのパフォーマンス

base_productsproductsというテーブルが必要です。 productはすべてbase_productに属します。

は、base_productから列を継承する必要がありますが、同じ名前の列もいくつかあります。 productsの列データはbase_products列を上書きしますが、productsの列がNULLでない場合のみです。

製品を取得するためのクエリは、理論的にはこのようなものになります。この場合IFNULL

SELECT 
    p.id, 
    IFNULL(p.sku, _p.sku) AS sku, 
    IFNULL(p.ean, _p.ean) AS ean, 
    IFNULL(p.weight, _p.weight) AS weight 
    IFNULL(p.unit_id, _p.unit_id) AS unit_id 
FROM products AS p 
JOIN base_products as _p ON p.id = _p.product_id 
WHERE IFNULL(p.weight, _p.weight) > 500 

が潜在的に非常に大きなテーブルを照会するために使用されています。

この文脈ではIFNULLの使用が許容されるでしょうか?または、大規模なデータセットを照会するときにパフォーマンスが低下しますか?しかし

SELECT p.id, 
     COALESCE(p.sku, _p.sku) AS sku, 
     COALESCE(p.ean, _p.ean) AS ean, 
     COALESCE(p.weight, _p.weight) AS weight 
     COALESCE(p.unit_id, _p.unit_id) AS unit_id 
FROM products p JOIN 
    base_products _p 
    ON p.id = _p.product_id 
WHERE COALESCE(p.weight, _p.weight) > 500; 

、パフォーマンスとは何の関係もありません:それはANSI標準関数であるので、

+1

ヒューのダミーデータを作成し、実行方法を知るためにEXPLAINを実行します。 –

+0

sqlのようなものを継承システムのように使用することには注意してください。 – Drew

+0

@ user2864740これは、WHERE IFNULL(p.name、_p.name)= 'something''も動作しなければならないということを付け加えておきます。 'products'のデータの存在に基づいて、どこで行うのかを実際に選択する必要があります – Boyd

答えて

0

まず、私はずっと、coalesce()を好みます。

このクエリのパフォーマンスの問題は、COALESCE()(またはIFNULL())とほとんど関係ありません。これは単なる関数呼び出しです。実際の問題は、JOINWHEREです。これらはデータの移動に関連しています。 JOINは簡単です。JOINで使用される列にインデックスが付いていることを確認してください。

WHEREはトリッキーです。たくさんの行を除外すると、いくつかの選択肢があるかもしれませんが、もっと複雑です。私はJOINインデックスに焦点を当てます。

+0

ありがとうございます!ちょうどあなたの脳を選んで..良いパフォーマンスを維持しながら、上書きする列を持つこの継承を達成し、where節でそれらを持つ良い方法がありますか?あるいは、アプリケーションコードでこのデータを選択し、 'products'テーブル – Boyd

+0

@Boydに重複したデータが存在するのを受け入れる方が良いでしょう。 。 。あなたの方法は問題ないと思います。実際にパフォーマンスに問題がある場合は、その問題に対処してください。それ以外の場合は、ビューを使用して反復コードを避けることができます。 –

関連する問題