Вычисление самого большого «внутреннего» прямоугольника внутри сложной формы географии SQL - PullRequest
0 голосов
/ 27 апреля 2018

Я пытаюсь создавать отчеты, которые связаны с перекрытием географических границ.

В качестве упрощенного примера, почтовые индексы внутри DMA (назначенная маркетинговая зона).

У меня есть данные географии SQL, описывающие форму многоугольника прямого доступа к памяти, и данные географии SQL, описывающие формы многоугольника почтовых индексов США.

Я бы хотел узнать:

  1. Какие почтовые индексы полностью содержатся в DMA
  2. Какие почтовые индексы частично перекрывают DMA.
  3. Какой процент площади перекрывающегося почтового индекса находится внутри DMA

Я могу получить эту информацию, используя методы STWithin и STIntersection, сравнивая области. Однако я сталкиваюсь с некоторыми узкими местами с высокой производительностью.

Первое, что я сделал, это вычислил и записал внешние ограничительные рамки DMA и форм почтового индекса, сохранил их в таблице и проиндексировал на этих данных. Это позволило мне исключить все почтовые индексы, которые не могут перекрываться с DMA.

Пример: * * один тысяча двадцать-одна

SELECT  ...
FROM Locations d
INNER JOIN Locations z ON z.Type = 5 -- Zip Code
WHERE d.ID = @DMAID
AND NOT (
   z.MaxLat < d.MinLat
OR z.MinLat > d.MaxLat
OR z.MaxLng < d.MinLng
OR z.MinLng > d.MaxLng
)

Однако, в зависимости от количества получаемых почтовых индексов для сравнения, запрос все равно может занять слишком много времени, чтобы его можно было использовать в производственной среде.

Я надеюсь, что может быть какой-то способ вычислить "внутреннюю ограничивающую рамку" (из-за отсутствия лучшего слова), подобную тому, как STEnvelope вычисляет "внешнюю ограничивающую рамку"

Идея в том, какой самый большой прямоугольник поместится в предоставленной форме? Это позволило бы быстро запросить ограничивающие прямоугольники почтового индекса, которые полностью помещаются внутри него, оставив (надеюсь) гораздо меньший набор почтовых индексов, который потребовал бы более точного STIntersection.

Редактировать: Добавлено 5/25/2018

После обсуждения с Риком, приведенного ниже, я включил детали плана выполнения для двух запросов, один с использованием шаблона AND NOT (> OR, а другой - с помощью AND (<= AND. </p>).

SELECT ID
FROM Locations
WHERE LocationType = 5
AND CountryCode = 'US'
AND NOT (
   MaxLat < 32.750
OR MinLat > 34.823
OR MaxLng < -118.951
OR MinLng > -117.646
)

SELECT ID
FROM Locations
WHERE LocationType = 5
AND CountryCode = 'US'
AND MaxLat >= 32.750
AND MinLat <= 34.823
AND MaxLng >= -118.951
AND MinLng <= -117.646

Вот XML-представление планов выполнения:

<ShowPlanXML xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan" Version="1.5" Build="13.0.4001.0">
  <BatchSequence>
    <Batch>
      <Statements>
        <StmtSimple StatementText="SELECT ID&#xd;&#xa;FROM Locations&#xd;&#xa;WHERE LocationType = 5&#xd;&#xa;AND CountryCode = &apos;US&apos;&#xd;&#xa;AND NOT (&#xd;&#xa;   MaxLat &lt; 32.750&#xd;&#xa;OR MinLat &gt; 34.823&#xd;&#xa;OR MaxLng &lt; -118.951&#xd;&#xa;OR MinLng &gt; -117.646&#xd;&#xa;)" StatementId="1" StatementCompId="1" StatementType="SELECT" RetrievedFromCache="false" StatementSubTreeCost="0.0226731" StatementEstRows="88.5595" SecurityPolicyApplied="false" StatementOptmLevel="TRIVIAL" QueryHash="0xA63252C178F68E1" QueryPlanHash="0x48CBE2D413E8362B" CardinalityEstimationModelVersion="70">
          <StatementSetOptions QUOTED_IDENTIFIER="true" ARITHABORT="true" CONCAT_NULL_YIELDS_NULL="true" ANSI_NULLS="true" ANSI_PADDING="true" ANSI_WARNINGS="true" NUMERIC_ROUNDABORT="false"></StatementSetOptions>
          <QueryPlan CachedPlanSize="24" CompileTime="3" CompileCPU="3" CompileMemory="344">
            <MemoryGrantInfo SerialRequiredMemory="0" SerialDesiredMemory="0"></MemoryGrantInfo>
            <OptimizerHardwareDependentProperties EstimatedAvailableMemoryGrant="2949120" EstimatedPagesCached="5898240" EstimatedAvailableDegreeOfParallelism="8" MaxCompileMemory="635169608"></OptimizerHardwareDependentProperties>
            <RelOp NodeId="0" PhysicalOp="Nested Loops" LogicalOp="Inner Join" EstimateRows="88.5595" EstimatedRowsRead="1466.67" EstimateIO="0.0209028" EstimateCPU="0.00177034" AvgRowSize="50" EstimatedTotalSubtreeCost="0.0226731" TableCardinality="86546" Parallel="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row">
              <OutputList>
                <ColumnReference Database="****" Schema="[dbo]" Table="[Locations]" Column="ID"></ColumnReference>
              </OutputList>
              <NestedLoops Optimized="0">
                <OuterReferences>
                  <ColumnReference Column="Expr1003"></ColumnReference>
                  <ColumnReference Column="Expr1004"></ColumnReference>
                  <ColumnReference Column="Expr1002"></ColumnReference>
                </OuterReferences>
                <RelOp NodeId="1" PhysicalOp="Compute Scalar" LogicalOp="Compute Scalar" EstimateRows="1" EstimateIO="0" EstimateCPU="0" AvgRowSize="37" EstimatedTotalSubtreeCost="0" Parallel="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row">
                  <OutputList>
                    <ColumnReference Column="Expr1003"></ColumnReference>
                    <ColumnReference Column="Expr1004"></ColumnReference>
                    <ColumnReference Column="Expr1002"></ColumnReference>
                  </OutputList>
                  <ComputeScalar>
                    <DefinedValues>
                      <DefinedValue>
                        <ValueVector>
                          <ColumnReference Column="Expr1003"></ColumnReference>
                          <ColumnReference Column="Expr1004"></ColumnReference>
                          <ColumnReference Column="Expr1002"></ColumnReference>
                        </ValueVector>
                        <ScalarOperator ScalarString="GetRangeWithMismatchedTypes(NULL,(34.823),(42))">
                          <Intrinsic FunctionName="GetRangeWithMismatchedTypes">
                            <ScalarOperator>
                              <Const ConstValue="NULL"></Const>
                            </ScalarOperator>
                            <ScalarOperator>
                              <Const ConstValue="(34.823)"></Const>
                            </ScalarOperator>
                            <ScalarOperator>
                              <Const ConstValue="(42)"></Const>
                            </ScalarOperator>
                          </Intrinsic>
                        </ScalarOperator>
                      </DefinedValue>
                    </DefinedValues>
                    <RelOp NodeId="2" PhysicalOp="Constant Scan" LogicalOp="Constant Scan" EstimateRows="1" EstimateIO="0" EstimateCPU="0" AvgRowSize="0" EstimatedTotalSubtreeCost="0" Parallel="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row">
                      <OutputList></OutputList>
                      <ConstantScan></ConstantScan>
                    </RelOp>
                  </ComputeScalar>
                </RelOp>
                <RelOp NodeId="3" PhysicalOp="Index Seek" LogicalOp="Index Seek" EstimateRows="88.5595" EstimatedRowsRead="1466.67" EstimateIO="0.0209028" EstimateCPU="0.00177034" AvgRowSize="50" EstimatedTotalSubtreeCost="0.0226731" TableCardinality="86546" Parallel="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row">
                  <OutputList>
                    <ColumnReference Database="****" Schema="[dbo]" Table="[Locations]" Column="ID"></ColumnReference>
                  </OutputList>
                  <IndexScan Ordered="1" ScanDirection="FORWARD" ForcedIndex="0" ForceSeek="0" ForceScan="0" NoExpandHint="0" Storage="RowStore">
                    <DefinedValues>
                      <DefinedValue>
                        <ColumnReference Database="****" Schema="[dbo]" Table="[Locations]" Column="ID"></ColumnReference>
                      </DefinedValue>
                    </DefinedValues>
                    <Object Database="****" Schema="[dbo]" Table="[Locations]" Index="[IX_MinMax]" IndexKind="NonClustered" Storage="RowStore"></Object>
                    <SeekPredicates>
                      <SeekPredicateNew>
                        <SeekKeys>
                          <Prefix ScanType="EQ">
                            <RangeColumns>
                              <ColumnReference Database="****" Schema="[dbo]" Table="[Locations]" Column="LocationType"></ColumnReference>
                              <ColumnReference Database="****" Schema="[dbo]" Table="[Locations]" Column="CountryCode"></ColumnReference>
                            </RangeColumns>
                            <RangeExpressions>
                              <ScalarOperator ScalarString="(5)">
                                <Const ConstValue="(5)"></Const>
                              </ScalarOperator>
                              <ScalarOperator ScalarString="N&apos;US&apos;">
                                <Const ConstValue="N&apos;US&apos;"></Const>
                              </ScalarOperator>
                            </RangeExpressions>
                          </Prefix>
                          <StartRange ScanType="GT">
                            <RangeColumns>
                              <ColumnReference Database="****" Schema="[dbo]" Table="[Locations]" Column="MinLat"></ColumnReference>
                            </RangeColumns>
                            <RangeExpressions>
                              <ScalarOperator ScalarString="[Expr1003]">
                                <Identifier>
                                  <ColumnReference Column="Expr1003"></ColumnReference>
                                </Identifier>
                              </ScalarOperator>
                            </RangeExpressions>
                          </StartRange>
                          <EndRange ScanType="LT">
                            <RangeColumns>
                              <ColumnReference Database="****" Schema="[dbo]" Table="[Locations]" Column="MinLat"></ColumnReference>
                            </RangeColumns>
                            <RangeExpressions>
                              <ScalarOperator ScalarString="[Expr1004]">
                                <Identifier>
                                  <ColumnReference Column="Expr1004"></ColumnReference>
                                </Identifier>
                              </ScalarOperator>
                            </RangeExpressions>
                          </EndRange>
                        </SeekKeys>
                      </SeekPredicateNew>
                    </SeekPredicates>
                    <Predicate>
                      <ScalarOperator ScalarString="****.[dbo].[Locations].[MaxLat]&gt;=(32.750) AND ****.[dbo].[Locations].[MaxLng]&gt;=(-118.951) AND ****.[dbo].[Locations].[MinLng]&lt;=(-117.646)">
                        <Logical Operation="AND">
                          <ScalarOperator>
                            <Compare CompareOp="GE">
                              <ScalarOperator>
                                <Identifier>
                                  <ColumnReference Database="****" Schema="[dbo]" Table="[Locations]" Column="MaxLat"></ColumnReference>
                                </Identifier>
                              </ScalarOperator>
                              <ScalarOperator>
                                <Const ConstValue="(32.750)"></Const>
                              </ScalarOperator>
                            </Compare>
                          </ScalarOperator>
                          <ScalarOperator>
                            <Compare CompareOp="GE">
                              <ScalarOperator>
                                <Identifier>
                                  <ColumnReference Database="****" Schema="[dbo]" Table="[Locations]" Column="MaxLng"></ColumnReference>
                                </Identifier>
                              </ScalarOperator>
                              <ScalarOperator>
                                <Const ConstValue="(-118.951)"></Const>
                              </ScalarOperator>
                            </Compare>
                          </ScalarOperator>
                          <ScalarOperator>
                            <Compare CompareOp="LE">
                              <ScalarOperator>
                                <Identifier>
                                  <ColumnReference Database="****" Schema="[dbo]" Table="[Locations]" Column="MinLng"></ColumnReference>
                                </Identifier>
                              </ScalarOperator>
                              <ScalarOperator>
                                <Const ConstValue="(-117.646)"></Const>
                              </ScalarOperator>
                            </Compare>
                          </ScalarOperator>
                        </Logical>
                      </ScalarOperator>
                    </Predicate>
                  </IndexScan>
                </RelOp>
              </NestedLoops>
            </RelOp>
          </QueryPlan>
        </StmtSimple>
        <StmtSimple StatementText="&#xd;&#xa;&#xd;&#xa;SELECT ID&#xd;&#xa;FROM Locations&#xd;&#xa;WHERE LocationType = 5&#xd;&#xa;AND CountryCode = &apos;US&apos;&#xd;&#xa;AND MaxLat &gt;= 32.750&#xd;&#xa;AND MinLat &lt;= 34.823&#xd;&#xa;AND MaxLng &gt;= -118.951&#xd;&#xa;AND MinLng &lt;= -117.646" StatementId="2" StatementCompId="2" StatementType="SELECT" RetrievedFromCache="false" StatementSubTreeCost="0.0226731" StatementEstRows="88.5595" SecurityPolicyApplied="false" StatementOptmLevel="TRIVIAL" QueryHash="0xA63252C178F68E1" QueryPlanHash="0x48CBE2D413E8362B" CardinalityEstimationModelVersion="70" ParameterizedText="(@1 tinyint,@2 varchar(8000),@3 numeric(5,3),@4 numeric(5,3),@5 numeric(6,3),@6 numeric(6,3))SELECT [ID] FROM [Locations] WHERE [LocationType]=@1 AND [CountryCode]=@2 AND [MaxLat]&gt;=@3 AND [MinLat]&lt;=@4 AND [MaxLng]&gt;=@5 AND [MinLng]&lt;=@6">
          <StatementSetOptions QUOTED_IDENTIFIER="true" ARITHABORT="true" CONCAT_NULL_YIELDS_NULL="true" ANSI_NULLS="true" ANSI_PADDING="true" ANSI_WARNINGS="true" NUMERIC_ROUNDABORT="false"></StatementSetOptions>
          <QueryPlan CachedPlanSize="32" CompileTime="2" CompileCPU="2" CompileMemory="336">
            <MemoryGrantInfo SerialRequiredMemory="0" SerialDesiredMemory="0"></MemoryGrantInfo>
            <OptimizerHardwareDependentProperties EstimatedAvailableMemoryGrant="2949120" EstimatedPagesCached="5898240" EstimatedAvailableDegreeOfParallelism="8" MaxCompileMemory="635178856"></OptimizerHardwareDependentProperties>
            <RelOp NodeId="0" PhysicalOp="Nested Loops" LogicalOp="Inner Join" EstimateRows="88.5595" EstimatedRowsRead="1466.67" EstimateIO="0.0209028" EstimateCPU="0.00177034" AvgRowSize="50" EstimatedTotalSubtreeCost="0.0226731" TableCardinality="86546" Parallel="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row">
              <OutputList>
                <ColumnReference Database="****" Schema="[dbo]" Table="[Locations]" Column="ID"></ColumnReference>
              </OutputList>
              <NestedLoops Optimized="0">
                <OuterReferences>
                  <ColumnReference Column="Expr1005"></ColumnReference>
                  <ColumnReference Column="Expr1006"></ColumnReference>
                  <ColumnReference Column="Expr1004"></ColumnReference>
                </OuterReferences>
                <RelOp NodeId="1" PhysicalOp="Compute Scalar" LogicalOp="Compute Scalar" EstimateRows="1" EstimateIO="0" EstimateCPU="0" AvgRowSize="37" EstimatedTotalSubtreeCost="0" Parallel="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row">
                  <OutputList>
                    <ColumnReference Column="Expr1005"></ColumnReference>
                    <ColumnReference Column="Expr1006"></ColumnReference>
                    <ColumnReference Column="Expr1004"></ColumnReference>
                  </OutputList>
                  <ComputeScalar>
                    <DefinedValues>
                      <DefinedValue>
                        <ValueVector>
                          <ColumnReference Column="Expr1005"></ColumnReference>
                          <ColumnReference Column="Expr1006"></ColumnReference>
                          <ColumnReference Column="Expr1004"></ColumnReference>
                        </ValueVector>
                        <ScalarOperator ScalarString="GetRangeWithMismatchedTypes(NULL,[@4],(42))">
                          <Intrinsic FunctionName="GetRangeWithMismatchedTypes">
                            <ScalarOperator>
                              <Const ConstValue="NULL"></Const>
                            </ScalarOperator>
                            <ScalarOperator>
                              <Identifier>
                                <ColumnReference Column="@4"></ColumnReference>
                              </Identifier>
                            </ScalarOperator>
                            <ScalarOperator>
                              <Const ConstValue="(42)"></Const>
                            </ScalarOperator>
                          </Intrinsic>
                        </ScalarOperator>
                      </DefinedValue>
                    </DefinedValues>
                    <RelOp NodeId="2" PhysicalOp="Constant Scan" LogicalOp="Constant Scan" EstimateRows="1" EstimateIO="0" EstimateCPU="0" AvgRowSize="0" EstimatedTotalSubtreeCost="0" Parallel="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row">
                      <OutputList></OutputList>
                      <ConstantScan></ConstantScan>
                    </RelOp>
                  </ComputeScalar>
                </RelOp>
                <RelOp NodeId="3" PhysicalOp="Index Seek" LogicalOp="Index Seek" EstimateRows="88.5595" EstimatedRowsRead="1466.67" EstimateIO="0.0209028" EstimateCPU="0.00177034" AvgRowSize="50" EstimatedTotalSubtreeCost="0.0226731" TableCardinality="86546" Parallel="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row">
                  <OutputList>
                    <ColumnReference Database="****" Schema="[dbo]" Table="[Locations]" Column="ID"></ColumnReference>
                  </OutputList>
                  <IndexScan Ordered="1" ScanDirection="FORWARD" ForcedIndex="0" ForceSeek="0" ForceScan="0" NoExpandHint="0" Storage="RowStore">
                    <DefinedValues>
                      <DefinedValue>
                        <ColumnReference Database="****" Schema="[dbo]" Table="[Locations]" Column="ID"></ColumnReference>
                      </DefinedValue>
                    </DefinedValues>
                    <Object Database="****" Schema="[dbo]" Table="[Locations]" Index="[IX_MinMax]" IndexKind="NonClustered" Storage="RowStore"></Object>
                    <SeekPredicates>
                      <SeekPredicateNew>
                        <SeekKeys>
                          <Prefix ScanType="EQ">
                            <RangeColumns>
                              <ColumnReference Database="****" Schema="[dbo]" Table="[Locations]" Column="LocationType"></ColumnReference>
                              <ColumnReference Database="****" Schema="[dbo]" Table="[Locations]" Column="CountryCode"></ColumnReference>
                            </RangeColumns>
                            <RangeExpressions>
                              <ScalarOperator ScalarString="CONVERT_IMPLICIT(int,[@1],0)">
                                <Identifier>
                                  <ColumnReference Column="ConstExpr1002">
                                    <ScalarOperator>
                                      <Convert DataType="int" Style="0" Implicit="1">
                                        <ScalarOperator>
                                          <Identifier>
                                            <ColumnReference Column="@1"></ColumnReference>
                                          </Identifier>
                                        </ScalarOperator>
                                      </Convert>
                                    </ScalarOperator>
                                  </ColumnReference>
                                </Identifier>
                              </ScalarOperator>
                              <ScalarOperator ScalarString="CONVERT_IMPLICIT(nvarchar(4000),[@2],0)">
                                <Identifier>
                                  <ColumnReference Column="ConstExpr1003">
                                    <ScalarOperator>
                                      <Convert DataType="nvarchar" Length="8000" Style="0" Implicit="1">
                                        <ScalarOperator>
                                          <Identifier>
                                            <ColumnReference Column="@2"></ColumnReference>
                                          </Identifier>
                                        </ScalarOperator>
                                      </Convert>
                                    </ScalarOperator>
                                  </ColumnReference>
                                </Identifier>
                              </ScalarOperator>
                            </RangeExpressions>
                          </Prefix>
                          <StartRange ScanType="GT">
                            <RangeColumns>
                              <ColumnReference Database="****" Schema="[dbo]" Table="[Locations]" Column="MinLat"></ColumnReference>
                            </RangeColumns>
                            <RangeExpressions>
                              <ScalarOperator ScalarString="[Expr1005]">
                                <Identifier>
                                  <ColumnReference Column="Expr1005"></ColumnReference>
                                </Identifier>
                              </ScalarOperator>
                            </RangeExpressions>
                          </StartRange>
                          <EndRange ScanType="LT">
                            <RangeColumns>
                              <ColumnReference Database="****" Schema="[dbo]" Table="[Locations]" Column="MinLat"></ColumnReference>
                            </RangeColumns>
                            <RangeExpressions>
                              <ScalarOperator ScalarString="[Expr1006]">
                                <Identifier>
                                  <ColumnReference Column="Expr1006"></ColumnReference>
                                </Identifier>
                              </ScalarOperator>
                            </RangeExpressions>
                          </EndRange>
                        </SeekKeys>
                      </SeekPredicateNew>
                    </SeekPredicates>
                    <Predicate>
                      <ScalarOperator ScalarString="****.[dbo].[Locations].[MaxLat]&gt;=[@3] AND ****.[dbo].[Locations].[MaxLng]&gt;=[@5] AND ****.[dbo].[Locations].[MinLng]&lt;=[@6]">
                        <Logical Operation="AND">
                          <ScalarOperator>
                            <Compare CompareOp="GE">
                              <ScalarOperator>
                                <Identifier>
                                  <ColumnReference Database="****" Schema="[dbo]" Table="[Locations]" Column="MaxLat"></ColumnReference>
                                </Identifier>
                              </ScalarOperator>
                              <ScalarOperator>
                                <Identifier>
                                  <ColumnReference Column="@3"></ColumnReference>
                                </Identifier>
                              </ScalarOperator>
                            </Compare>
                          </ScalarOperator>
                          <ScalarOperator>
                            <Compare CompareOp="GE">
                              <ScalarOperator>
                                <Identifier>
                                  <ColumnReference Database="****" Schema="[dbo]" Table="[Locations]" Column="MaxLng"></ColumnReference>
                                </Identifier>
                              </ScalarOperator>
                              <ScalarOperator>
                                <Identifier>
                                  <ColumnReference Column="@5"></ColumnReference>
                                </Identifier>
                              </ScalarOperator>
                            </Compare>
                          </ScalarOperator>
                          <ScalarOperator>
                            <Compare CompareOp="LE">
                              <ScalarOperator>
                                <Identifier>
                                  <ColumnReference Database="****" Schema="[dbo]" Table="[Locations]" Column="MinLng"></ColumnReference>
                                </Identifier>
                              </ScalarOperator>
                              <ScalarOperator>
                                <Identifier>
                                  <ColumnReference Column="@6"></ColumnReference>
                                </Identifier>
                              </ScalarOperator>
                            </Compare>
                          </ScalarOperator>
                        </Logical>
                      </ScalarOperator>
                    </Predicate>
                  </IndexScan>
                </RelOp>
              </NestedLoops>
            </RelOp>
            <ParameterList>
              <ColumnReference Column="@6" ParameterDataType="numeric(6,3)" ParameterCompiledValue="(-117.646)"></ColumnReference>
              <ColumnReference Column="@5" ParameterDataType="numeric(6,3)" ParameterCompiledValue="(-118.951)"></ColumnReference>
              <ColumnReference Column="@4" ParameterDataType="numeric(5,3)" ParameterCompiledValue="(34.823)"></ColumnReference>
              <ColumnReference Column="@3" ParameterDataType="numeric(5,3)" ParameterCompiledValue="(32.750)"></ColumnReference>
              <ColumnReference Column="@2" ParameterDataType="varchar(8000)" ParameterCompiledValue="&apos;US&apos;"></ColumnReference>
              <ColumnReference Column="@1" ParameterDataType="tinyint" ParameterCompiledValue="(5)"></ColumnReference>
            </ParameterList>
          </QueryPlan>
        </StmtSimple>
      </Statements>
    </Batch>
  </BatchSequence>
</ShowPlanXML>

1 Ответ

0 голосов
/ 19 мая 2018

(Эти комментарии относятся к MySQL; они могут относиться или не относиться к другим поставщикам. Ответ был написан до того, как стало известно, что MSSql был targer.)

Используйте закон Де Моргана, чтобы избежать NOT и OR:

AND z.MaxLat >= d.MinLat
AND z.MinLat <= d.MaxLat
AND z.MaxLng >= d.MinLng
AND z.MinLng <= d.MaxLng

Не делайте все SELECT, пока не найдете нужные вам почтовые индексы и / или dmas. Этот может разрешить эффективный запуск подзапроса в индексе.

SELECT ...
    FROM ( SELECT z.id
               FROM zips z  JOIN dmas d
               WHERE d.ID = @DMAID
                 AND z.Type = 5
                 AND z.MaxLat >= d.MinLat ...
         ) x
    JOIN zips z2 ON x.id = z2.id

с этим индексом на zips:

INDEX(Type,  -- first
      MinLat, MaxLat, MinLng, MaxLng,  -- any order
      id)   -- last

ИЛИ, НЕ

Индекс BTree ...

  • Для «точечного запроса», который находит одну строку по заданному ключу.
  • «Диапазон» или строки. Это включает a > 5, a BETWEEN 5 AND 10, `c LIKE 'foo%' и т. Д.
  • Другие типы запросов менее эффективны.
  • NOT обычно включает два диапазона, часто охватывающих большую часть индекса: «все до X и все после X».
  • OR (включая один столбец) включает в себя прыжок через таблицу.

Когда задействованы несколько таблиц (или несколько столбцов), все становится более сложным.

  • Два стола - в основном безнадежные.
  • Два столбца - a = 5 AND ... может получить выгоду от составного индекса , начиная с с a, поскольку a был протестирован с =.

Я рекомендовал индекс из 6 столбцов «составной» и «охватывающий»:

  • «Составной», поскольку он содержит более 1 столбца.
  • Начинается с Type, что проверяется с помощью '=', поэтому в игру может войти больше столбцов.
  • Второй столбец (MinLat) протестирован с диапазоном, поэтому остальные столбцы не будут использоваться для фильтрации или сортировки.
  • «Covering» вступает в игру, потому что все столбцов (из zips) в подзапросе («производная» таблица) включены в индекс. Это позволяет действию происходить только в BTree индекса, не касаясь BTree «данных».
  • В этом сценарии использования мы не знаем, какой столбец лучше всего ставить на второе место в индексе; Я выбрал один произвольно.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...