2014-03-07 3 views
2

나는 구매 버튼을 누를 때 사용자를 위해 부품을 찾기 위해 규칙 세트 (더 정확하게는 7 개)를 사용하는 사용자 정의 상점 사이트를 가지고 있습니다. 이러한 규칙 중 일부는 같은 : (허용되는 지역 당 하나의 판매자) 소비자와 동일한 주, 도시 및 지구에 최초의 판매자에 대한더 나은 성능 : UNION 쿼리 대 separete 쿼리?

  • 판매자 위가없는 경우 부분과 동일한 그룹의 판매자를 한 곳에서 얻을 수 있으며 같은 도시에있는 경우
  • 위 판매자에게 부품이 없으면 같은 도시의 판매자를 찾으십시오.
  • 등등 .. .

나는 쿼리의 첫 번째 결과 만 가져 오려면 각 규칙의 거대한 결합에서 약 300 줄의 SQL (쉽게 읽을 수 있도록 형식이 지정됨)이 있어야합니다.

이 방법이 더 좋은지 잘 모르겠습니까? 아니면 다음 번 호출하기 전에 결과가 있는지를 확인하기 위해 조건부 왕복 7 건을 순서 검사에서하는 것이 더 좋습니다.

대다수의 사용자는 규칙 4를 따르고 SQL Server에 대해 4 회 왕복하며 거대한 조합 쿼리의 결과가 10 만 개 미만의 부분에서 1 초 이내에 반환 될 것으로 예상합니다 표.

문제는이 사이트가 사용 가능한 부분의 온도로 자라기 시작한 경우 SQL Server가 1 회의 여행에서 필요한 것만 반환하는 거대한 쿼리로 작업을 처리하는 것이 더 좋습니다. 별도의 쿼리를 호출합니까?

우리는이 작업에 고전적인 ASP를 사용하고 있습니다 (예! Old school, 아시겠습니까?).

검색어 자체를 살펴 봐야하는지 알려주세요.

편집 :

SELECT TOP 1 regras.ids, regras.idCadastro, regras.regra, e.descricao AS nomeEstado, cd.descricao AS nomeCidade, b.nome AS nomeBairro 
FROM ( 
    SELECT dbo.group_concat(idPecaItem) AS ids, idCadastro, '1' AS regra 
    FROM ( 
     SELECT TOP 2 idPecaItem, idCadastro 
     FROM pecasItens 
     WHERE COALESCE(pecasItens.idCadastro, 0) = (CASE WHEN EXISTS( 
      SELECT TOP 1 COALESCE(pi.idCadastro, 0) 
      FROM pecasItens pi 
      LEFT JOIN cadastros c ON pi.idCadastro = c.idCadastro 
      WHERE (pi.idCadastro IS NULL OR c.tipoParceiro = 'c') AND idPeca = 31740 AND idPedidoItem IS NULL AND dataEntrada <= '2014-3-13' AND devolucaoSolicitada IS NULL 
      GROUP BY pi.idCadastro 
      HAVING COUNT(pi.idPecaItem) >= 2 
     ) THEN ( 
      SELECT TOP 1 COALESCE(pi.idCadastro, 0) 
      FROM pecasItens pi 
      LEFT JOIN cadastros c ON pi.idCadastro = c.idCadastro 
      WHERE (pi.idCadastro IS NULL OR c.tipoParceiro = 'c') AND idPeca = 31740 AND idPedidoItem IS NULL AND dataEntrada <= '2014-3-13' AND devolucaoSolicitada IS NULL 
      GROUP BY pi.idCadastro 
      HAVING COUNT(pi.idPecaItem) >= 2 
     ) ELSE NULL END) 
     AND idPeca = 31740 AND idPedidoItem IS NULL AND dataEntrada <= '2014-3-13' AND devolucaoSolicitada IS NULL 
    ) regra1 
    GROUP BY idCadastro 

    UNION 

    SELECT dbo.group_concat(idPecaItem) AS ids, idCadastro, '2' AS regra 
    FROM ( 
     SELECT TOP 2 idPecaItem, idCadastro 
     FROM pecasItens 
     WHERE COALESCE(pecasItens.idCadastro, 0) = (CASE WHEN EXISTS( 
      SELECT TOP 1 COALESCE(pi.idCadastro, 0) 
      FROM pecasItens pi 
      LEFT JOIN cadastros c ON pi.idCadastro = c.idCadastro AND c.tipoParceiro = 'r' AND c.idCadastroGrupo = 1 
      WHERE pi.idCadastro IS NOT NULL AND idPeca = 31740 AND idPedidoItem IS NULL AND dataEntrada <= '2014-3-13' AND devolucaoSolicitada IS NULL 
      GROUP BY pi.idCadastro 
      HAVING COUNT(pi.idPecaItem) >= 2 
     ) THEN ( 
      SELECT TOP 1 COALESCE(pi.idCadastro, 0) 
      FROM pecasItens pi 
      LEFT JOIN cadastros c ON pi.idCadastro = c.idCadastro AND c.tipoParceiro = 'r' AND c.idCadastroGrupo = 1 
      WHERE pi.idCadastro IS NOT NULL AND idPeca = 31740 AND idPedidoItem IS NULL AND dataEntrada <= '2014-3-13' AND devolucaoSolicitada IS NULL 
      GROUP BY pi.idCadastro 
      HAVING COUNT(pi.idPecaItem) >= 2 
     ) ELSE NULL END) 
     AND idPeca = 31740 AND idPedidoItem IS NULL AND dataEntrada <= '2014-3-13' AND devolucaoSolicitada IS NULL 
    ) regra2 
    GROUP BY idCadastro 

    UNION 

    SELECT dbo.group_concat(idPecaItem) AS ids, idCadastro, '3' AS regra 
    FROM ( 
     SELECT TOP 2 idPecaItem, idCadastro 
     FROM pecasItens 
     WHERE COALESCE(pecasItens.idCadastro, 0) = (CASE WHEN EXISTS( 
      SELECT TOP 1 COALESCE(pi.idCadastro, 0) 
      FROM pecasItens pi 
      LEFT JOIN cadastros c ON pi.idCadastro = c.idCadastro AND c.tipoParceiro = 'r' AND c.idCadastroGrupo = 1 
      INNER JOIN cadastrosCidades cc ON c.idCadastro = cc.idCadastro AND cc.idCidade = 4850 
      WHERE pi.idCadastro IS NOT NULL AND idPeca = 31740 AND idPedidoItem IS NULL AND dataEntrada <= '2014-3-13' AND devolucaoSolicitada IS NULL 
      GROUP BY pi.idCadastro 
      HAVING COUNT(pi.idPecaItem) >= 2 
     ) THEN ( 
      SELECT TOP 1 COALESCE(pi.idCadastro, 0) 
      FROM pecasItens pi 
      LEFT JOIN cadastros c ON pi.idCadastro = c.idCadastro AND c.tipoParceiro = 'r' AND c.idCadastroGrupo = 1 
      INNER JOIN cadastrosCidades cc ON c.idCadastro = cc.idCadastro AND cc.idCidade = 4850 
      WHERE pi.idCadastro IS NOT NULL AND idPeca = 31740 AND idPedidoItem IS NULL AND dataEntrada <= '2014-3-13' AND devolucaoSolicitada IS NULL 
      GROUP BY pi.idCadastro 
      HAVING COUNT(pi.idPecaItem) >= 2 
     ) ELSE NULL END) 
     AND idPeca = 31740 AND idPedidoItem IS NULL AND dataEntrada <= '2014-3-13' AND devolucaoSolicitada IS NULL 
    ) regra3 
    GROUP BY idCadastro 
    UNION 

    SELECT dbo.group_concat(idPecaItem) AS ids, idCadastro, '4' AS regra 
    FROM ( 
     SELECT TOP 2 idPecaItem, idCadastro 
     FROM pecasItens 
     WHERE COALESCE(pecasItens.idCadastro, 0) = (CASE WHEN EXISTS( 
      SELECT TOP 1 COALESCE(pi.idCadastro, 0) 
      FROM pecasItens pi 
      INNER JOIN cadastros c ON pi.idCadastro = c.idCadastro AND c.tipoParceiro = 'r' 
      INNER JOIN cadastrosGrupos cg ON c.idCadastroGrupo = cg.idCadastroGrupo AND cg.idMarca = 2 
      INNER JOIN cadastrosCidades cc ON c.idCadastro = cc.idCadastro AND cc.idCidade = 4850 
      WHERE pi.idCadastro IS NOT NULL AND idPeca = 31740 AND idPedidoItem IS NULL AND dataEntrada <= '2014-3-13' AND devolucaoSolicitada IS NULL 
      GROUP BY pi.idCadastro 
      HAVING COUNT(pi.idPecaItem) >= 2 
     ) THEN ( 
      SELECT TOP 1 COALESCE(pi.idCadastro, 0) 
      FROM pecasItens pi 
      INNER JOIN cadastros c ON pi.idCadastro = c.idCadastro AND c.tipoParceiro = 'r' 
      INNER JOIN cadastrosGrupos cg ON c.idCadastroGrupo = cg.idCadastroGrupo AND cg.idMarca = 2 
      INNER JOIN cadastrosCidades cc ON c.idCadastro = cc.idCadastro AND cc.idCidade = 4850 
      WHERE pi.idCadastro IS NOT NULL AND idPeca = 31740 AND idPedidoItem IS NULL AND dataEntrada <= '2014-3-13' AND devolucaoSolicitada IS NULL 
      GROUP BY pi.idCadastro 
      HAVING COUNT(pi.idPecaItem) >= 2 
     ) ELSE NULL END) 
     AND idPeca = 31740 AND idPedidoItem IS NULL AND dataEntrada <= '2014-3-13' AND devolucaoSolicitada IS NULL 
    ) regra4 
    GROUP BY idCadastro 

    UNION 

    SELECT dbo.group_concat(idPecaItem) AS ids, idCadastro, '5' AS regra 
    FROM ( 
     SELECT TOP 2 idPecaItem, idCadastro 
     FROM pecasItens 
     WHERE COALESCE(pecasItens.idCadastro, 0) = (CASE WHEN EXISTS( 
      SELECT TOP 1 COALESCE(pi.idCadastro, 0) 
      FROM pecasItens pi 
      INNER JOIN cadastrosGrupos cg ON pi.idCadastro = cg.idCadastroMontadora AND cg.idCadastroGrupo = 1 
      WHERE pi.idCadastro IS NOT NULL AND idPeca = 31740 AND idPedidoItem IS NULL AND dataEntrada <= '2014-3-13' AND devolucaoSolicitada IS NULL 
      GROUP BY pi.idCadastro 
      HAVING COUNT(pi.idPecaItem) >= 2 
     ) THEN ( 
      SELECT TOP 1 COALESCE(pi.idCadastro, 0) 
      FROM pecasItens pi 
      INNER JOIN cadastrosGrupos cg ON pi.idCadastro = cg.idCadastroMontadora AND cg.idCadastroGrupo = 1 
      WHERE pi.idCadastro IS NOT NULL AND idPeca = 31740 AND idPedidoItem IS NULL AND dataEntrada <= '2014-3-13' AND devolucaoSolicitada IS NULL 
      GROUP BY pi.idCadastro 
      HAVING COUNT(pi.idPecaItem) >= 2 
     ) ELSE NULL END) 
     AND idPeca = 31740 AND idPedidoItem IS NULL AND dataEntrada <= '2014-3-13' AND devolucaoSolicitada IS NULL 
    ) regra5 
    GROUP BY idCadastro 

    UNION 

    SELECT dbo.group_concat(idPecaItem) AS ids, idCadastro, '6' AS regra 
    FROM ( 
     SELECT TOP 2 idPecaItem, idCadastro 
     FROM pecasItens 
     WHERE COALESCE(pecasItens.idCadastro, 0) = (CASE WHEN EXISTS( 
      SELECT TOP 1 COALESCE(pi.idCadastro, 0) 
      FROM pecasItens pi 
      LEFT JOIN cadastros c ON pi.idCadastro = c.idCadastro AND c.tipoParceiro = 'r' AND c.idEstado = 25 AND c.atendeEstadoTodo = 1 
      WHERE pi.idCadastro IS NOT NULL AND idPeca = 31740 AND idPedidoItem IS NULL AND dataEntrada <= '2014-3-13' AND devolucaoSolicitada IS NULL 
      GROUP BY pi.idCadastro 
      HAVING COUNT(pi.idPecaItem) >= 2 
     ) THEN ( 
      SELECT TOP 1 COALESCE(pi.idCadastro, 0) 
      FROM pecasItens pi 
      LEFT JOIN cadastros c ON pi.idCadastro = c.idCadastro AND c.tipoParceiro = 'r' AND c.idEstado = 25 AND c.atendeEstadoTodo = 1 
      WHERE pi.idCadastro IS NOT NULL AND idPeca = 31740 AND idPedidoItem IS NULL AND dataEntrada <= '2014-3-13' AND devolucaoSolicitada IS NULL 
      GROUP BY pi.idCadastro 
      HAVING COUNT(pi.idPecaItem) >= 2 
     ) ELSE NULL END) 
     AND idPeca = 31740 AND idPedidoItem IS NULL AND dataEntrada <= '2014-3-13' AND devolucaoSolicitada IS NULL 
    ) regra6 
    GROUP BY idCadastro 

    UNION 

    SELECT dbo.group_concat(idPecaItem) AS ids, idCadastro, '7' AS regra 
    FROM ( 
     SELECT TOP 2 idPecaItem, idCadastro 
     FROM pecasItens 
     WHERE COALESCE(pecasItens.idCadastro, 0) = (CASE WHEN EXISTS( 
      SELECT TOP 1 COALESCE(pi.idCadastro, 0) 
      FROM pecasItens pi 
      LEFT JOIN cadastros c ON pi.idCadastro = c.idCadastro AND c.tipoParceiro = 'r' AND c.atendeBrasilTodo = 1 
      WHERE pi.idCadastro IS NOT NULL AND idPeca = 31740 AND idPedidoItem IS NULL AND dataEntrada <= '2014-3-13' AND devolucaoSolicitada IS NULL 
      GROUP BY pi.idCadastro 
      HAVING COUNT(pi.idPecaItem) >= 2 
     ) THEN ( 
      SELECT TOP 1 COALESCE(pi.idCadastro, 0) 
      FROM pecasItens pi 
      LEFT JOIN cadastros c ON pi.idCadastro = c.idCadastro AND c.tipoParceiro = 'r' AND c.atendeBrasilTodo = 1 
      WHERE pi.idCadastro IS NOT NULL AND idPeca = 31740 AND idPedidoItem IS NULL AND dataEntrada <= '2014-3-13' AND devolucaoSolicitada IS NULL 
      GROUP BY pi.idCadastro 
      HAVING COUNT(pi.idPecaItem) >= 2 
     ) ELSE NULL END) 
     AND idPeca = 31740 AND idPedidoItem IS NULL AND dataEntrada <= '2014-3-13' AND devolucaoSolicitada IS NULL 
    ) regra7 
    GROUP BY idCadastro 
) regras 
LEFT JOIN cadastros c ON regras.idCadastro = c.idCadastro 
LEFT JOIN listaEstados e ON c.idEstado = e.idEstado 
LEFT JOIN listaCidades cd ON c.idCidade = cd.idCidade 
LEFT JOIN listaBairros b ON c.idBairro = b.idBairro 
ORDER BY regra ASC 

아니, MySQL은 아니다 :

그냥 결론을 위해, 여기에 내가 지금 사용하고 쿼리입니다. group_concat()은이 사용자의 맞춤 집계입니다 http://groupconcat.codeplex.com/

+0

어떻게 생각하십니까,이 시점에서 쿼리를 볼 필요가 있습니까? – Alexander

+1

죄송합니다. 나는 그것을 얻지 못했다. 영어가 제 집 언어가 아닙니다. 당신이 아이러니 컬하고 쿼리를 게시하라고 말하고 있습니다. 맞아, 재밌니? – rcdmk

+1

조기 최적화 ("http://c2.com/cgi/wiki?PrematureOptimization")에주의하십시오! 어쨌든 그것을 생각하면 좋다. 이 방법으로 생각하면 ... 두 가지 선택 사항이 있으므로 병목 현상이 될 경우 중간에서 프로세스를 전환 할 수 있습니다. 선택의 여지가 여기 있습니다. 이러한 쿼리를 공용체로 푸시하는 경향이 있습니다 (특히 기본 쿼리가이 컨텍스트에서만 사용되는 경우). 세 번째 옵션은 필터링 된 레코드 집합 (SQL은 위대한)을 100 개 레코드로 반환하고 코드에서 의사 결정을 내리는 것입니다 (그리고 단위 테스트에서 어떻게 결정할 것인가). – BlackjacketMack

답변

3

거의 모든 경우에 RDBMS는 첫 번째 행을 얻는 데 훨씬 좋은 위치에 있습니다.

쿼리는 다음과 같습니다 경우

,

SELECT TOP 1 * 
FROM (
    SELECT ... FROM ... -- Query #1 
UNION ALL 
    SELECT ... FROM ... -- Query #2 
UNION ALL 
    ... 
UNION ALL 
    SELECT ... FROM ... -- Query #7 
) 

최적화는 당신이 필요로하는 결과를 생성 규칙, 그것은 하나를 지배 할 어떤에서 쿼리를 중지 똑똑는 4 개의 규칙 또는 규칙 일곱. 또한 최적화 프로그램은 쿼리를 병렬로 실행할 수 있습니다. 데이터에 훨씬 가깝기 때문에 쿼리 로직의 일부를 RDBMS에서 멀리 이동 시켜서 "현저히"능가 할 수 있다고 상상하기 어렵습니다.

+0

고마워,이게 내가 해냈어. 동시 액세스 수가 늘어 났을 때 성능을 저하시키지 않는다면 궁금합니다. 그러나 결과를 찾았을 때 최적화 프로그램이 멈추는 것을 알지 못합니다. 알아 둘만한. – rcdmk

+0

나에게 뭔가 더 명확히 해 주시겠습니까? 쿼리를 실행 순서대로 반환합니까? 내가 선택한'최상위 1 * (선택 x, tbl에서 q로 1, 여기서 y = 1 조합 선택 x, tbl에서 2는 y = 2)를 선택합니다. tb order by q asc'를 말합니다. 규칙이 순서대로 반환 될 것이라는 보장이 필요한가? 그렇지 않으면 약간의 성능 만 저하 될 것인가? – rcdmk

+0

@rcdmk 'UNION'의 순서는 보장되지 않습니다. 임의의 순서로 데이터를 가져올 수 있으며, 동일한 RDBMS에서 동일하지 않을 수도 있습니다. 좋은 옵티마이 저가 개별 SELECT를 병렬로 실행할 수 있으므로 "경쟁에서이기는"행을 얻을 수 있습니다. 'ORDER BY'를 추가해도 단일 행인 쿼리의 결과에 적용되므로 아무 것도 변경되지 않습니다. – dasblinkenlight

1

내 의도는 SQL로 작업을 두지 만 쿼리가 유니온이 아니도록 다시 구조화하는 것입니다. 대신에 결과가 발견되는 즉시 내부 쿼리가 일련의 개별 쿼리를 반환한다는 저장 프로 시저를 제공 할 수 있어야합니다. 가짜 SQL은 이런 식으로 시작하고 아마 그 길을 따라 개선 될 수 있습니다.

CREATE PROC GetBestSeller (Part, State, City, District) AS BEGIN 

    DECLARE @Seller INT 

    SELECT TOP 1 @idSeller = idSeller FROM your first choice 

    IF @Seller IS NOT NULL BEGIN 
    SELECT * FROM Seller WHERE idSeller = @idSeller 
    RETURN 
    END 

    SELECT TOP 1 @idSeller = idSeller FROM your second choice 
    SELECT * FROM Seller WHERE idSeller = @idSeller 
    RETURN 
    END 

..and so one 
END 

편집 : @Dasblinkenlight 아마 SQL Server의 쿼리 최적화 프로그램은 아마 내부적으로 이런 종류의 작업을 수행 할 것을 그것의 권리에 있고 그 정말로에 무슨 일이 벌어지고 있는지 여부를 알 프로파일 볼 수 있었다 노동 조합.

+0

이것은 살펴볼 항목입니다. 누군가가 이것에 대한 비교를합니까? 나는하기 전에 묻는 것을 생각했지만, 어쨌든 그것을해야 할 것 같아요. – rcdmk