2011-09-20 6 views
3

Joomla와 같은 주요 시스템은 주 기사 데이터베이스에 쉼표로 구분 된 텍스트로 태그를 저장하지만 기사, 태그 및 태그 관계로 세 테이블의 표준화 된 시스템이 선호됩니다 자료 Wordpress 사용). 구조와 독서에 대한 많은 토론과 질문이 있습니다. 그러나 우리는 세 개의 테이블에 삽입해야하므로 가장 좋은 INSERT 명령을 찾을 수 없었습니다. 한 SQL 실행을 통해이 프로세스를 신속하게 실행하는 방법은 무엇입니까? 또는 먼저 기사를 삽입 한 다음 각 태그를 삽입하고 마지막으로 관계를 작성해야합니다.3 테이블 시스템에서 태그를 삽입하는 방법

또 다른 질문은 태그의 고유성에 관한 것입니다. 이 시스템의 가장 큰 장점은 각 용어를 한 번만 저장하면됩니다 (해당 기사에 연결). 중복을 피하기 위해 mysql UNIQUE를 사용하는 것이 실용적인가요? 또는 (어딘가에서 읽었을 때) 태그의 전체 목록을 배열로 읽어서 중복을 찾아서 태그 ID를 잡아서 용어를 저장하지 않아도됩니까?

윌 세 개의 개별 단계로 전체 과정 :

  1. INSERT 기사
  2. INSERT 태그 UNIQUE와 만 관계없이 관계
  3. 각 태그의 ID 찾기 및 문서 ID
  4. 에 관계를 만들

맞습니까? 내가 물었던 이유는 사람들이 태그를 배열로 잡고 비교를하는 것을 보았 기 때문입니다. 나에게는 매우 느리고 특히 UPDATE의 경우 성능이 저하됩니다.

답변

4

한 번에 하나의 테이블에만 삽입 할 수 있습니다.

하나의 솔루션은 트리거를 사용하고 다른 하나는 트랜잭션을 사용하는 것입니다.
첫 번째 엔진은 어떤 엔진과도 사용할 수 있으며, 후자는 InnoDB 또는 유사 엔진이 필요합니다.

필드에 UNIQUE 색인을 넣었는지 확인하십시오. 블랙홀 테이블

에 트리거를 사용하여 2

-1- 사용하는 거래

START TRANSACTION; 

INSERT IGNORE INTO tag (name) VALUES ('$example1', '$example2'); 
INSERT INTO article (title, body) VALUES ('$title','$body'); 
SET @article_id = LAST_INSERT_ID(); 
INSERT INTO tag_link (tag_id, article_id) 
    SELECT t.id, @article_id FROM tag t WHERE t.name IN ('$example1','$example2'); 

COMMIT; 

는 다음 필드 타입 blackhole의 테이블을 생성.

title: varchar(255) 
body: text 
tag1: varchar(50) DEFAULT NULL 
tag2: varchar(50) DEFAULT NULL 
... 
add as many tags as you want. 

당신을 위해 실제 저장 작업을 수행 할 블랙홀 테이블에 AFTER INSERT 트리거를 추가합니다.

DELIMITER $$ 

CREATE TRIGGER ai_bh_newacticle_each AFTER INSERT ON bh_newacticle FOR EACH ROW 
BEGIN 
    INSERT IGNORE INTO tag (name) VALUES (new.tag1, new.tag2,...,new.tag25); 
    INSERT INTO article (title, body) VALUES (new.title,new.body); 
    SET @article_id = LAST_INSERT_ID(); 
    INSERT INTO tag_link (tag_id, article_id) 
    SELECT t.id, @article_id FROM tag t 
    WHERE t.name IN (new.tag1, new.tag2,...,new.tag25); 
END$$ 

DELIMITER ; 

DELIMITER $$ 

지금 당신은 단지 하나의 문에 태그 문서를 삽입 할 수 있습니다

돌아 가기
INSERT INTO bh_newarticle (title, body, tag1, tag2, tag3) 
    VALUES ('$title','$body','$tag1','$tag2','$tag3'); 

질문에

내가 맞죠? 내가 물었던 이유는 사람들이 태그를 배열로 잡고 비교를하는 것을 보았 기 때문입니다. 나에게는 매우 느리고 특히 UPDATE의 경우 성능이 저하됩니다.

태그는 제한된 수의 경우에만 유용합니다. tag.name에 (고유 한) 색인을 넣으면 태그를 찾는 것이 매우 빠를 것입니다. 10.000 태그도 있습니다. 정확히 일치하는 것을 찾고 있기 때문입니다. 그리고 정말로 서두르다면 언제든지 태그 테이블을 name 필드의 hash index 테이블로 만들 수 있습니다.
태그 조회가 느려지는 것에 대해 걱정할 필요가 없습니다.

기사 당 태그가 너무 많아서는 안됩니다. 5 좋은 시작 같습니다. 10이 너무 많습니다.

링크
http://dev.mysql.com/doc/refman/5.0/en/create-trigger.html
http://dev.mysql.com/doc/refman/5.0/en/blackhole-storage-engine.html

1

단일 명령문에서 3 개의 테이블에 삽입 할 수 없지만 한 트랜잭션에서 3 개의 삽입 명령문을 실행할 수 있습니다.

중복을 피하기 위해 고유 한 것으로 태그 열을 선언 할 때 문제가 표시되지 않습니다. 태그를 테이블에 삽입하기 전에 태그가 존재하는지 여부를 항상 확인할 수 있습니다. 더 좋은 것은 태그 simply upsert입니다.

1

단일 쿼리를 실행하여 각 INSERT를 실행하면 "해결 방법"이 없으며 하나라도 존재할 수도 있습니다. 따라서 3 개의 테이블에 3 개의 삽입이 가능합니다.

고유 태그가 필요한 경우 예 - 중복 방지를 위해 UNIQUE 제약 조건을 사용하는 것이 좋습니다.

단순한 INSERT IGNORE MySQL 기능을 사용하면 삽입하기 전에 레코드 존재 여부를 피할 수 있습니다.

+0

물론 항상 거기에는'해결 방법 '이 있습니다. – Johan

0

는 DBMS 기능의 예에 따라 몇 가지 가능성이 : 대신 트리거의 저장 프로 시저, 그것을 가능하게하는 다른 하나의 SQL 문을 사용하여 삽입,하지만 난 할 수있다 하나의 트랜잭션에서 3 개의 테이블 모두에 삽입하는 것조차 중요하지 않기 때문에 가치가 없다고 생각합니다. 기사가 저장되었지만 태그가 저장되지 않으면 나쁘지 않습니다 ...하지만 필요한 경우 저장 프로 시저는 다음과 같습니다. 복잡한 논리를 허용하기 때문에이 작업에 가장 적합하며 y에 서브 프로그램을 작성할 수도 있습니다. 모든 SQL을 exec 할 수있는 우리 프로그램은 1 줄에서 필요할 때마다 호출합니다 ...

태그 필드의 태그 테이블과 필드의 rel 테이블 (article_id, tag)에 고유 인덱스를 만들 수 있습니다.

+0

'기사가 저장되었지만 태그가 저장되지 못하면 나쁘지 않습니다. ' 넌센스 – Johan

+0

왜? 저자는 항상 기사에 태그를 추가 할 수 있습니다 (기사가 보관 된 경우 ...) – skazska

+0

태그는 기사를 찾는 데 사용됩니다. 태그가 손실 될 수있는 경우 기사를 찾는 것이 매우 어려울 것입니다. 아주 나쁜 디자인. 응용 프로그램은 그냥 작동해야하며, 문서 작성자가 이중 확인 및 손을 잡아야합니다. – Johan

관련 문제