2

1 つの DATE 列と 1 つの TIME 列を含む、数百万行のテーブルがあります。

テーブル構造を変更することはできませんが、新しいインデックスを追加することは可能です。

このクエリを考慮すると:

SELECT * FROM Table WHERE TIMESTAMP(Date, Time) BETWEEN 'X' AND 'Y';

日付と時刻の列にインデックスがあり、日付と時刻の列にもインデックスがありますが、TIMESTAMP 関数を使用すると、クエリはインデックスを使用しません。

質問は、(データ型ではなく) TIMESTAMP 関数を使用するインデックスを作成できるかどうかです。そうでない場合、上記のクエリを変更してインデックスを使用する方法はありますか?

クエリを短く簡潔に保ち、可能であれば日付ごとに繰り返す必要がないようにしています。

編集:

では、MySQL は式インデックスをサポートしていないため、このクエリを変更して日付または (日付、時刻) インデックスを使用する方法はありますか?

4

2 に答える 2

4

これは式インデックスと呼ばれますが、すべての RDBMS ブランドがこれをサポートしているわけではありません。

これは MySQL では実行できません。

最も近いのは、MariaDB と呼ばれる MySQL のフォークでサポートされている永続的な仮想列です。しかし、スキーマを変更できないのであれば、別の RDBMS パッケージに切り替えることも問題外だと思います。

PostgreSQL は、式インデックスをサポートする RDBMS の例です。


回避策として、日付列のみをフィルタリングすることをお勧めします。これにより、その列にインデックスがある場合、検索を大幅に絞り込むことができます。

SELECT * FROM Table WHERE Date BETWEEN 'Xdate' AND 'Ydate' 
  AND CASE WHEN Date = 'Xdate' THEN TIMESTAMP(Date, Time) >= 'X' 
           WHEN Date = 'Ydate' THEN TIMESTAMP(Date, Time) <= 'Y'
           ELSE 1 END;

次に、テーブル全体のすべての行ではなく、データのサブセットに対してのみ TIMESTAMP() 式を評価する必要があります。上記の例では、日付が日付範囲の開始または終了と一致する場合にのみ TIMESTAMP() を評価します。これは、Xdate と Ydate の間の日付範囲が非常に長く、多くの行に一致する場合に便利です。その間のすべての日付に対してその関数を実行する必要はありません。

私は上記の式をテストしていないので、何かがずれている場合は申し訳ありませんが、アイデアを得る必要があると思います.

于 2013-04-17T00:19:13.580 に答える
2

私の提案は、関数を逆にしてクエリを書き直して、X と Y のタイムスタンプのみから日付と時刻を生成することです。

SELECT * 
FROM Table 
WHERE (Date, Time) >= ('Xdate', 'Xtime') 
  AND (Date, Time) <= ('Ydate', 'Ytime') ;

コメントで @BillKarwin が説明したように、それはインデックスの恩恵を受けません。したがって、(Date, Time)インデックスを使用できるように書き直します。

SELECT * 
FROM Table 
WHERE 'Xdate' = 'Ydate'
          AND Date = 'Xdate' AND Time >= 'Xtime' AND Time <= 'Ytime'
   OR 'Xdate' < 'Ydate'
          AND ( Date = 'Xdate' AND Time >= 'Xtime'
             OR Date > 'Xdate' AND Date < 'Ydate'
             OR Date = 'Ydate' AND Time <= 'Ytime'
              ) ;

TIMESTAMP()このように、関数の呼び出しはまったく必要ありません。

于 2013-04-17T00:49:35.943 に答える