2013-07-21 2 views
1

검색이 가능한 웹 사이트가 있습니다. MySQL 데이터베이스 실행. 그것이 검색 엔진 (스핑크스, Lucene 등)의 성능에 도움이 될지 궁금해? 어떻게 될까요? 면 탐색으로 검색 할 수 있습니까? 텍스트 검색이 있다면 도움이 될 것입니다. 그러나 대부분의 쿼리가 다음과 같은 경우 이점이 있습니다.비 텍스트 검색은 검색 엔진의 이점을 제공합니까?

select SQL_CALC_FOUND_ROWS distinct tableA.id 
    from tableA as A 
     join tableB as B1 on A.id=B1.tablea_id 
     join tableB as B2 on A.id=B2.tablea_id 
     join tableB as B3 on A.id=B3.tablea_id 
where 
    B1.value in ([list of ints here]) 
and 
    B2.value in ([another list of ints here]) 
and 
    B2.value in ([one more list of ints here]) 
order by ~A.updated_at 
limit <from>,<amount>; 

아이디어는, 제 목록에서 tableBtableA 갖는 값의 행을 찾아으로 정렬 등 번째 목록에서 tableB 이들 갖는 값을두고 모든 발견 한계를 계산 한 후에 여과한다.

tableAtableB는 다음과 같습니다

create table tableA (
    id int(11) not null autoincrement, 
    ... 
    updated_at timestamp not null, 
    primary key (`id`), 
    key `ix_tablea_updated_at` (`updated_at`) 
) engine=InnoDB; 

create table tableB (
    tablea_id int(11) not null, 
    value int(11) not null, 
    key `ix_tableb_tablea_id` (`tablea_id`), 
    key `ix_tableb_value` (`value`) 
) engine=InnoDB; 

tableA는 ~ 200K 행이 포함되어 있습니다. tableB은 ~ 1.2M 행을 포함합니다. B.value in ([list of ints])의 수는 쿼리와 쿼리가 다르며 lists of ints과 같습니다.

검색 엔진을 사용할 수있는 방법이 없다면 다른 방법으로 성능을 향상시킬 수 있습니까?

나는 문제가 order by ~A.updated_at이고 발견 된 행을 발견했다고 말할 수 있습니다. MySQL 자체를 사용하여 정렬 및 계산 속도를 높이는 방법이 있습니까?

추신. 실례합니다. 당신이 나를 이해할 수 있기를 바랍니다.

답변

2

왜 같은 ID로 세 번 테이블 B를 가입 하시겠습니까? 당신은 하나의 가입과 같은 효과를 얻을 수 있습니다 : 당신은 심지어 B(value)에 인덱스를하는 경우

select SQL_CALC_FOUND_ROWS distinct tableA.id 
from tableA A join 
    tableB B 
    on A.id = B.tablea_id 
where B.value in ([big big combined list of ints here]) 
order by A.updated_at 
limit <from>, <amount>; 

B(value, tablea_id)는 성능은 다음과 같습니다

세 가지 목록을 갖는
select SQL_CALC_FOUND_ROWS distinct tableA.id 
from tableA A join 
    tableB B 
    on A.id = B.tablea_id 
where B.value in ([list of ints here]) and 
     B.value in ([another list of ints here]) and 
     B.value in ([one more list of ints here]) 
order by A.updated_at 
limit <from>, <amount>; 

당신도 할 수 있도록 중복 훨씬 나아.

편집 :

아니, 쿼리는 당신이 생각했던 방식으로 작동하지 않습니다. be 테이블에 참여할 때마다 행 수를 곱합니다. 예를 들어, A 테이블의 QQQ 값에는 B 테이블의 10 개의 해당 행이 있습니다. 첫 번째 조인은 10 개의 행을 가져오고 두 번째 조인은 100, 세 번째 조인은 1,000을 곱합니다. 이것은 아마도 성능 문제의 근원입니다.

동일한 열에서 연속 필터링 만하고 있습니다. 실제로, 나는 당신이 정말로 모든 것을 알고 싶어한다고 생각한다. 세 개의 목록에 각각 B id가 어디에 있는지. 그렇다면, 이것은 "설정에서 설정합니다"쿼리, 그리고 쉽게 group by을 사용하여 수행 :

select SQL_CALC_FOUND_ROWS tableA.id 
from tableA A join 
    tableB B 
    on A.id = B.tablea_id 
group by tableA.id 
having sum(B.value in ([list of ints here])) > 0 and 
     sum(B.value in ([another list of ints here])) > 0 and 
     sum(B.value in ([one more list of ints here])) > 0 
order by A.updated_at 
limit <from>, <amount>; 

원래 접근 방식은 아마도 작업을 수행 - 재미있다. 일반적으로 값 중 하나가 데이터에 나타나지 않으면 조인이 행을 반환하지 않는 한 매우 비효율적입니다.

+0

'tableB'을 한 번만 결합하면'B.value'가 3 개의 목록 모두에 동시에 있어야합니다. (해야하지 않습니까?). 그리고 제가 여러 번 가입한다면, A를 필터링하여 첫 번째 목록의 B.values와 두 번째 목록의 등등을 따로 따로 가질 수 있습니다. 내가 잘못? 내가 말하는 것처럼 작동하는 것 같다. 나는'ix_tableb_value' 인덱스를 가지고 있습니다. – zaquest

+0

동일한 열을 필터링하지 않습니다.내가 B에서 A (1,2,3) 값에 어떤 행을 가지고 있다면, B를 3 번 ​​합치면 나에게 [(1,1,1), (1,1,2), (1,1,3), (1,2,1), .., (3,3,3)] 그리고 나서 B1.value = 1, B2.value = 2, B3.value = 3을 찾을 수 있습니다. 그 맞습니까? – zaquest

+0

'group by '을 사용하면 같은 결과를 얻을 수 있지만 실행하는 데 2 ​​배의 시간이 걸립니다. 어쨌든, 노력해 주셔서 감사합니다. – zaquest

관련 문제