4

特定のタイムスタンプより前にのみ存在するソースサイトを見つけようとしています。このクエリは、この仕事には非常に貧弱なようです。最適化する方法や改善される可能性のあるインデックスはありますか?

select distinct sourcesite 
  from contentmeta 
  where timestamp <= '2011-03-15'
  and sourcesite not in (
    select distinct sourcesite 
      from contentmeta 
      where timestamp>'2011-03-15'
  );

ソースサイトとタイムスタンプにインデックスがありますが、クエリにはまだ長い時間がかかります

mysql> EXPLAIN select distinct sourcesite from contentmeta where timestamp <= '2011-03-15' and sourcesite not in (select distinct sourcesite from contentmeta where timestamp>'2011-03-15');
+----+--------------------+-------------+----------------+---------------+----------+---------+------+--------+-------------------------------------------------+
| id | select_type        | table       | type           | possible_keys | key      | key_len | ref  | rows   | Extra                                           |
+----+--------------------+-------------+----------------+---------------+----------+---------+------+--------+-------------------------------------------------+
|  1 | PRIMARY            | contentmeta | index          | NULL          | sitetime | 14      | NULL | 725697 | Using where; Using index                        |
|  2 | DEPENDENT SUBQUERY | contentmeta | index_subquery | sitetime      | sitetime | 5       | func |     48 | Using index; Using where; Full scan on NULL key |
+----+--------------------+-------------+----------------+---------------+----------+---------+------+--------+-------------------------------------------------+
4

3 に答える 3

3

これは機能するはずです:

SELECT DISTINCT c1.sourcesite
FROM contentmeta c1
LEFT JOIN contentmeta c2
  ON c2.sourcesite = c1.sourcesite
  AND c2.timestamp > '2011-03-15'
WHERE c1.timestamp <= '2011-03-15'
  AND c2.sourcesite IS NULL

最適なパフォーマンスを得るには、contentmeta(sourcesitetimestamp)に複数列のインデックスを作成します。

一般に、派生テーブルはインデックスを利用できないため、結合はサブクエリよりもパフォーマンスが高くなります。

于 2012-05-09T18:34:49.430 に答える
3

サブクエリにはDISTINCTは必要ありません。また、NOT INで既にフィルタリングしているため、外部クエリのWHERE句も必要ありません。

試す:

select distinct sourcesite
from contentmeta
where sourcesite not in (
    select sourcesite
    from contentmeta
    where timestamp > '2011-03-15'
);
于 2012-05-09T18:39:17.200 に答える
1

「notin」は、多くのデータベースで最適化されていないことがわかりました。left outer join代わりに使用してください:

select distinct sourcesite 
from contentmeta cm 
left outer join
(
   select distinct sourcesite
   from contentmeta
   where timestamp>'2011-03-15'
) t
  on cm.sourcesite = t.sourcesite
where timestamp <= '2011-03-15' and t.sourcesite is null

sourcesiteこれは、がnullになることはないと想定しています。

于 2012-05-09T18:33:20.267 に答える