-1

2 つの大きなテーブルで単純な自然結合を実行しています。

  • ポリゴンには 68,000 行 (45 MB) が含まれます
  • roadshydro には約 200 万行 (210 MB) が含まれています。

これは、データベース エンジンが内部で自然結合を実行しながら、68,000*200 万行のデータ セットを作成するということですか。その場合、必要なメモリの量は 45*210 MB である必要があり、これは私のシステムの容量 (わずか 1.5 GB) よりもはるかに大きくなります。

このクエリを実行すると、5 分後にシステムがクラッシュします (突然シャットダウンします)。データベースで 250 MB のデータを処理できないのですか? では、データベースは何の役に立つのでしょうか?

"I am modifying the above Question to clear the doubts of readers. 29-02-2012 today."

上記の質問で「自然結合」という言葉に言及したため、多くの友人が混乱したようです。私が使用していた実際の空間クエリは次のとおりです。

select p.OID , r.OID
    from poygons as p , roadshydro as r
                Where st_intersects(p.the_geom , r.the_geom) ;

ここで、polygon と roadshydro テーブルには、それぞれ OID と the_geom という 2 つのフィールドがあります。明らかに、これは 2 つのテーブルの外積であり、いくつかの共通キーでの Natural Join ではありません。

上記のクエリを実行すると、メインメモリの消費量を監視します。それは何も起こりません。メモリ消費量はわずかでもなく、出力も得られませんが、CPU 使用率はほぼ 100% です。データベースはまったく計算を行っていないようです。ただし、クエリから where 句を削除すると、メイン メモリの消費量が徐々に高くなり (5 ~ 6 分後)、システムがクラッシュし、マシンが突然シャットダウンします。これが私が経験していることです。where句を削除することの何が特別なのですか?postgres がクエリの実行に失敗する理由 !! この行動にビックリ。

4

4 に答える 4

1

NATURAL JOINこの構文を使用する意味はほとんどありません。そうは言っても、結合が両方のテーブルのすべてのレコードと一致した場合、説明したクエリは2つのテーブルの積のみを生成します。

これは、両方のテーブルに同じ名前のフィールドがあり、すべてのレコードに同じ値が含まれている場合にのみ発生します。これは非常にまれですが、論理的に不可能ではないか、名前が一致する 2 つのテーブルにフィールドがない場合です。

私があなただったら、一致させたいフィールドを指定してNATURAL JOIN、プレーンを優先して破棄します。JOIN

それがクラッシュを解決するなら、それで問題ありませんが、もしそうなら、それは私にとって驚きです.

于 2011-10-12T08:03:46.717 に答える
0

この投稿に対する私のコメントは批判されているため、この件に関する私の意見を説明するために例を用意しました。

次の Oracle スクリプトは、NATURAL JOIN構文の使用に内在する危険性について私が考えるものを示しています。私はそれが不自然な例であることを認めますが、守備の発展のために、私の立場は正しいと信じています。

DROP TABLE TABLE1;
DROP TABLE TABLE2;

CREATE TABLE TABLE1 (
FIELD1   VARCHAR2(10),
FIELD2   VARCHAR2(10),
DESCR_T1 VARCHAR2(20)
);

CREATE TABLE TABLE2 (
FIELD1   VARCHAR2(10),
FIELD2   VARCHAR2(10),
DESCR_T2 VARCHAR2(20)
);

INSERT INTO TABLE1 VALUES('AAA','AAA',    'AAA_AAA_T1'   );
INSERT INTO TABLE1 VALUES('BBB','BBB',    'BBB_BBB_T1'   );
INSERT INTO TABLE1 VALUES('CCC','T1_CCC', 'CCC_T1_CCC_T1');
INSERT INTO TABLE1 VALUES('DDD','T1_DDD', 'DDD_T1_DDD_T1');
INSERT INTO TABLE1 VALUES('EEE',NULL    , 'EEE_NULL_T1'  );

INSERT INTO TABLE2 VALUES('AAA','AAA',    'AAA_AAA_T2'   );
INSERT INTO TABLE2 VALUES('BBB','BBB',    'BBB_BBB_T2'   );
INSERT INTO TABLE2 VALUES('CCC','T2_CCC', 'CCC_T1_CCC_T2');
INSERT INTO TABLE2 VALUES('DDD','T2_DDD', 'DDD_T1_DDD_T2');
INSERT INTO TABLE2 VALUES('EEE',NULL    , 'EEE_NULL_T2'  );

COMMIT;

-- try the following queries and review the results

SELECT 
  FIELD1, DESCR_T1, DESCR_T2 
FROM 
  TABLE1 NATURAL JOIN TABLE2;

SELECT 
  * 
FROM 
  TABLE1 NATURAL JOIN TABLE2;

SELECT 
  TABLE1.FIELD1, TABLE1.DESCR_T1, TABLE2.DESCR_T2 
FROM 
  TABLE1 JOIN 
    TABLE2 ON 
      TABLE2.FIELD1 = TABLE1.FIELD1 AND 
      TABLE2.FIELD2 = TABLE1.FIELD2;

SELECT * FROM 
  TABLE1 NATURAL JOIN TABLE2;

-- Issue the following statement then retry the previous 3 statements.
-- The 'NJs' silently change behaviour and produce radically different results
-- whereas the third requires hands-on attention.  I believe this third behaviour
-- is desirable.  (You could equally drop the column TABLE2.FIELD2 as dportas 
-- has suggested

-- ALTER TABLE TABLE2 RENAME COLUMN FIELD2 TO T2_FIELD2;
于 2011-11-16T13:56:56.933 に答える
0

Hugh のサンプル データを拡張すると、次の 2 つの NATURAL JOIN クエリの例が表示されます。うまくいけば、これらは Hugh が説明した問題から「安全」であり、NJ バージョンは実際には INNER JOIN バージョンよりも冗長ではない (そして私の意見では読みやすい) ことがわかります。

SELECT *
FROM 
(SELECT FIELD1, DESCR_T1 FROM TABLE1) T1
NATURAL JOIN
(SELECT FIELD1, DESCR_T2 FROM TABLE2) T2;

SELECT * 
FROM 
(SELECT FIELD1, FIELD2, DESCR_T1 FROM TABLE1) T1
NATURAL JOIN
(SELECT FIELD1, FIELD2, DESCR_T2 FROM TABLE2) T2;

ずさんなコードを書かない限り、Hugh が話している問題は存在しません。ずさんなコードを書くと、INNER JOIN も「安全ではありません」。このやり取りが示しているのは、自然な結合が常に十分に理解されているわけではないということです。それが、一部の人々が不当に彼らを疑う理由かもしれません。

于 2011-11-16T19:33:59.603 に答える
0

実際にはさまざまな要因に依存しますが、ほとんどの場合、使用している DBMS とその構成に依存します。

しかし、最大の誤解を解くために: DBMS はメモリ内のすべての行を保持する必要はありません: 一時テーブル (ハードディスク上) に書き込み、結果を提供できます...ゆっくりと...したがって、クラッシュしている場合は、それは正常ではありません。

もう一度言いますが、なぜ 68k*2M 行を要求しているのですか? つまり、136,000,000,000 行です。代わりに、いくつかのキーで直接結合したくないですか?

于 2011-10-12T06:34:26.977 に答える