简体   繁体   English

改进查询时间sql ip查找数据库

[英]improving query times a sql ip lookup database

I have a table in sql server 2005 which holds an ip range and the corresponding info (country / city / etc). 我在sql server 2005中有一个表,它包含一个ip范围和相应的信息(country / city / etc)。 There are approximately 3 million rows and it currently takes just over half a second to return a record based on the query below. 大约有300万行,目前根据下面的查询返回记录只需要半秒多。

DECLARE @ip BIGINT
SELECT @ip=3561360969

SELECT TOP 1 id, ipfrom, ipto, countrycode, countryname,region,city
FROM tbl_ip 
WHERE ipfrom <= @ip and @ip <= ipto

Can anyone offer any suggestions to improve the query time as the system I'm building needs to handle about 10 of these queries a second. 任何人都可以提供任何建议来改善查询时间,因为我正在构建的系统需要每秒处理大约10个这样的查询。 I've already done the following which hasn't improved the query time much... 我已经做了以下几点没有多少改进查询时间...

  • Set the database to read only 将数据库设置为只读
  • Used the NOLOCK table hint 使用了NOLOCK表提示
  • Indexed the ipfrom & ipto columns 索引ipfrom&ipto列

Any ideas would be much appreciated! 任何想法将不胜感激!

Tim 蒂姆

Edit: The xml execution plan is below: 编辑:xml执行计划如下:

<ShowPlanXML xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan" Version="1.0" Build="9.00.4053.00"><BatchSequence><Batch><Statements><StmtSimple StatementText="set statistics time on&#xd;&#xa;&#xd;" StatementId="1" StatementCompId="1" StatementType="SET STATS"/><StmtSimple StatementText="&#xa;DECLARE @ip BIGINT&#xd;&#xa;SELECT @ip=3561360969&#xd;" StatementId="2" StatementCompId="2" StatementType="ASSIGN"/><StmtSimple StatementText="&#xa;SELECT top 1 id, ipfrom, ipto, countrycode, countryname,region,city&#xd;&#xa;FROM tbl_ip &#xd;&#xa;WHERE ipfrom &lt;= @ip and @ip &lt;= ipto&#xd;&#xa;&#xd;" StatementId="3" StatementCompId="3" StatementType="SELECT" StatementSubTreeCost="0.00337934" StatementEstRows="1" StatementOptmLevel="TRIVIAL"><StatementSetOptions QUOTED_IDENTIFIER="false" ARITHABORT="true" CONCAT_NULL_YIELDS_NULL="false" ANSI_NULLS="false" ANSI_PADDING="false" ANSI_WARNINGS="false" NUMERIC_ROUNDABORT="false"/><QueryPlan CachedPlanSize="8" CompileTime="0" CompileCPU="0" CompileMemory="120"><RelOp NodeId="0" PhysicalOp="Top" LogicalOp="Top" EstimateRows="1" EstimateIO="0" EstimateCPU="1e-007" AvgRowSize="393" EstimatedTotalSubtreeCost="0.00337934" Parallel="0" EstimateRebinds="0" EstimateRewinds="0"><OutputList><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Id"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPFrom"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPTo"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryCode"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryName"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Region"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="City"/></OutputList><Top RowCount="0" IsPercent="0" WithTies="0"><TopExpression><ScalarOperator ScalarString="(1)"><Const ConstValue="(1)"/></ScalarOperator></TopExpression><RelOp NodeId="1" PhysicalOp="Clustered Index Scan" LogicalOp="Clustered Index Scan" EstimateRows="1" EstimateIO="28.1505" EstimateCPU="3.77105" AvgRowSize="393" EstimatedTotalSubtreeCost="0.00337724" Parallel="0" EstimateRebinds="0" EstimateRewinds="0"><OutputList><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Id"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPFrom"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPTo"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryCode"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryName"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Region"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="City"/></OutputList><IndexScan Ordered="0" ForcedIndex="0" NoExpandHint="0"><DefinedValues><DefinedValue><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Id"/></DefinedValue><DefinedValue><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPFrom"/></DefinedValue><DefinedValue><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPTo"/></DefinedValue><DefinedValue><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryCode"/></DefinedValue><DefinedValue><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryName"/></DefinedValue><DefinedValue><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Region"/></DefinedValue><DefinedValue><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="City"/></DefinedValue></DefinedValues><Object Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Index="[PK_tbl_IP2]"/><Predicate><ScalarOperator ScalarString="[RecruitmentIP].[dbo].[tbl_IP].[IPFrom]&lt;=[@ip] AND [@ip]&lt;=[RecruitmentIP].[dbo].[tbl_IP].[IPTo]"><Logical Operation="AND"><ScalarOperator><Compare CompareOp="LE"><ScalarOperator><Identifier><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPFrom"/></Identifier></ScalarOperator><ScalarOperator><Identifier><ColumnReference Column="@ip"/></Identifier></ScalarOperator></Compare></ScalarOperator><ScalarOperator><Compare CompareOp="LE"><ScalarOperator><Identifier><ColumnReference Column="@ip"/></Identifier></ScalarOperator><ScalarOperator><Identifier><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPTo"/></Identifier></ScalarOperator></Compare></ScalarOperator></Logical></ScalarOperator></Predicate></IndexScan></RelOp></Top></RelOp></QueryPlan></StmtSimple><StmtSimple StatementText="&#xa;set statistics time off" StatementId="4" StatementCompId="4" StatementType="SET STATS"/></Statements></Batch></BatchSequence></ShowPlanXML>

Execution plan with index on ipfrom, ipto 执行计划,索引为ipfrom,ipto

<ShowPlanXML xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan" Version="1.0" Build="9.00.4053.00"><BatchSequence><Batch><Statements><StmtSimple StatementText="DECLARE @ip BIGINT&#xd;&#xa;SELECT @ip=3561360969&#xd;" StatementId="1" StatementCompId="1" StatementType="ASSIGN"/><StmtSimple StatementText="&#xa;SELECT top 1 id, ipfrom, ipto, countrycode, countryname,region,city&#xd;&#xa;FROM tbl_ip &#xd;&#xa;WHERE ipfrom &lt;= @ip and @ip &lt;= ipto&#xd;&#xa;ORDER BY ipto&#xd;&#xa;" StatementId="2" StatementCompId="2" StatementType="SELECT" StatementSubTreeCost="224.264" StatementEstRows="1" StatementOptmLevel="FULL"><StatementSetOptions QUOTED_IDENTIFIER="false" ARITHABORT="true" CONCAT_NULL_YIELDS_NULL="false" ANSI_NULLS="false" ANSI_PADDING="false" ANSI_WARNINGS="false" NUMERIC_ROUNDABORT="false"/><QueryPlan CachedPlanSize="10" CompileTime="1" CompileCPU="1" CompileMemory="160"><RelOp NodeId="0" PhysicalOp="Sort" LogicalOp="TopN Sort" EstimateRows="1" EstimateIO="182.872" EstimateCPU="6.45397" AvgRowSize="393" EstimatedTotalSubtreeCost="224.264" Parallel="0" EstimateRebinds="0" EstimateRewinds="0"><OutputList><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Id"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPFrom"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPTo"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryCode"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryName"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Region"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="City"/></OutputList><MemoryFractions Input="0" Output="1"/><TopSort Distinct="0" Rows="1"><OrderBy><OrderByColumn Ascending="1"><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPTo"/></OrderByColumn></OrderBy><RelOp NodeId="1" PhysicalOp="Clustered Index Scan" LogicalOp="Clustered Index Scan" EstimateRows="308528" EstimateIO="28.1505" EstimateCPU="3.77105" AvgRowSize="393" EstimatedTotalSubtreeCost="31.9216" Parallel="0" EstimateRebinds="0" EstimateRewinds="0"><OutputList><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Id"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPFrom"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPTo"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryCode"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryName"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Region"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="City"/></OutputList><IndexScan Ordered="0" ForcedIndex="0" NoExpandHint="0"><DefinedValues><DefinedValue><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Id"/></DefinedValue><DefinedValue><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPFrom"/></DefinedValue><DefinedValue><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPTo"/></DefinedValue><DefinedValue><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryCode"/></DefinedValue><DefinedValue><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryName"/></DefinedValue><DefinedValue><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Region"/></DefinedValue><DefinedValue><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="City"/></DefinedValue></DefinedValues><Object Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Index="[PK_tbl_IP2]"/><Predicate><ScalarOperator ScalarString="[RecruitmentIP].[dbo].[tbl_IP].[IPFrom]&lt;=[@ip] AND [@ip]&lt;=[RecruitmentIP].[dbo].[tbl_IP].[IPTo]"><Logical Operation="AND"><ScalarOperator><Compare CompareOp="LE"><ScalarOperator><Identifier><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPFrom"/></Identifier></ScalarOperator><ScalarOperator><Identifier><ColumnReference Column="@ip"/></Identifier></ScalarOperator></Compare></ScalarOperator><ScalarOperator><Compare CompareOp="LE"><ScalarOperator><Identifier><ColumnReference Column="@ip"/></Identifier></ScalarOperator><ScalarOperator><Identifier><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPTo"/></Identifier></ScalarOperator></Compare></ScalarOperator></Logical></ScalarOperator></Predicate></IndexScan></RelOp></TopSort></RelOp></QueryPlan></StmtSimple></Statements></Batch></BatchSequence></ShowPlanXML>

execution plan for Martin Smiths query: Martin Smiths查询的执行计划:

<ShowPlanXML xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan" Version="1.0" Build="9.00.4053.00"><BatchSequence><Batch><Statements><StmtSimple StatementText="--set showplan_xml on&#xd;&#xa;&#xd;&#xa;set statistics time on&#xd;&#xa;&#xd;" StatementId="1" StatementCompId="1" StatementType="SET STATS"/><StmtSimple StatementText="&#xa;DECLARE @ip BIGINT&#xd;&#xa;SELECT @ip=3561360969&#xd;&#xa;&#xd;" StatementId="2" StatementCompId="2" StatementType="ASSIGN"/><StmtSimple StatementText="&#xa;SELECT id, ipfrom, ipto, countrycode, countryname,region,city FROM&#xd;&#xa;(&#xd;&#xa;SELECT TOP 1 id, ipfrom, ipto, countrycode, countryname,region,city&#xd;&#xa;FROM tbl_ip &#xd;&#xa;WHERE @ip &lt;= ipto&#xd;&#xa;ORDER BY ipto&#xd;&#xa;INTERSECT&#xd;&#xa;SELECT TOP 1 id, ipfrom, ipto, countrycode, countryname,region,city&#xd;&#xa;FROM tbl_ip &#xd;&#xa;WHERE ipfrom &lt;= @ip&#xd;&#xa;ORDER BY ipfrom DESC&#xd;&#xa;) ip&#xd;&#xa;&#xd;" StatementId="3" StatementCompId="3" StatementType="SELECT" StatementSubTreeCost="226.409" StatementEstRows="1" StatementOptmLevel="FULL"><StatementSetOptions QUOTED_IDENTIFIER="false" ARITHABORT="true" CONCAT_NULL_YIELDS_NULL="false" ANSI_NULLS="false" ANSI_PADDING="false" ANSI_WARNINGS="false" NUMERIC_ROUNDABORT="false"/><QueryPlan CachedPlanSize="33" CompileTime="6" CompileCPU="6" CompileMemory="376"><MissingIndexes><MissingIndexGroup Impact="10.1146"><MissingIndex Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]"><ColumnGroup Usage="INEQUALITY"><Column Name="[IPTo]" ColumnId="3"/></ColumnGroup><ColumnGroup Usage="INCLUDE"><Column Name="[Id]" ColumnId="1"/><Column Name="[IPFrom]" ColumnId="2"/><Column Name="[CountryCode]" ColumnId="4"/><Column Name="[CountryName]" ColumnId="5"/><Column Name="[Region]" ColumnId="6"/><Column Name="[City]" ColumnId="7"/></ColumnGroup></MissingIndex></MissingIndexGroup></MissingIndexes><RelOp NodeId="0" PhysicalOp="Nested Loops" LogicalOp="Left Semi Join" EstimateRows="1" EstimateIO="0" EstimateCPU="4.18e-006" AvgRowSize="86" EstimatedTotalSubtreeCost="226.409" Parallel="0" EstimateRebinds="0" EstimateRewinds="0"><OutputList><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Id"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPFrom"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPTo"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryCode"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryName"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Region"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="City"/></OutputList><NestedLoops Optimized="0"><Predicate><ScalarOperator ScalarString="[RecruitmentIP].[dbo].[tbl_IP].[Id]=[RecruitmentIP].[dbo].[tbl_IP].[Id] AND [RecruitmentIP].[dbo].[tbl_IP].[IPFrom] = [RecruitmentIP].[dbo].[tbl_IP].[IPFrom] AND [RecruitmentIP].[dbo].[tbl_IP].[IPTo] = [RecruitmentIP].[dbo].[tbl_IP].[IPTo] AND [RecruitmentIP].[dbo].[tbl_IP].[CountryCode] = [RecruitmentIP].[dbo].[tbl_IP].[CountryCode] AND [RecruitmentIP].[dbo].[tbl_IP].[CountryName] = [RecruitmentIP].[dbo].[tbl_IP].[CountryName] AND [RecruitmentIP].[dbo].[tbl_IP].[Region] = [RecruitmentIP].[dbo].[tbl_IP].[Region] AND [RecruitmentIP].[dbo].[tbl_IP].[City] = [RecruitmentIP].[dbo].[tbl_IP].[City]"><Logical Operation="AND"><ScalarOperator><Compare CompareOp="EQ"><ScalarOperator><Identifier><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Id"/></Identifier></ScalarOperator><ScalarOperator><Identifier><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Id"/></Identifier></ScalarOperator></Compare></ScalarOperator><ScalarOperator><Compare CompareOp="IS"><ScalarOperator><Identifier><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPFrom"/></Identifier></ScalarOperator><ScalarOperator><Identifier><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPFrom"/></Identifier></ScalarOperator></Compare></ScalarOperator><ScalarOperator><Compare CompareOp="IS"><ScalarOperator><Identifier><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPTo"/></Identifier></ScalarOperator><ScalarOperator><Identifier><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPTo"/></Identifier></ScalarOperator></Compare></ScalarOperator><ScalarOperator><Compare CompareOp="IS"><ScalarOperator><Identifier><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryCode"/></Identifier></ScalarOperator><ScalarOperator><Identifier><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryCode"/></Identifier></ScalarOperator></Compare></ScalarOperator><ScalarOperator><Compare CompareOp="IS"><ScalarOperator><Identifier><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryName"/></Identifier></ScalarOperator><ScalarOperator><Identifier><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryName"/></Identifier></ScalarOperator></Compare></ScalarOperator><ScalarOperator><Compare CompareOp="IS"><ScalarOperator><Identifier><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Region"/></Identifier></ScalarOperator><ScalarOperator><Identifier><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Region"/></Identifier></ScalarOperator></Compare></ScalarOperator><ScalarOperator><Compare CompareOp="IS"><ScalarOperator><Identifier><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="City"/></Identifier></ScalarOperator><ScalarOperator><Identifier><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="City"/></Identifier></ScalarOperator></Compare></ScalarOperator></Logical></ScalarOperator></Predicate><RelOp NodeId="1" PhysicalOp="Filter" LogicalOp="Filter" EstimateRows="1" EstimateIO="0" EstimateCPU="4.8e-007" AvgRowSize="86" EstimatedTotalSubtreeCost="226.399" Parallel="0" EstimateRebinds="0" EstimateRewinds="0"><OutputList><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Id"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPFrom"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPTo"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryCode"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryName"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Region"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="City"/></OutputList><Filter StartupExpression="0"><RelOp NodeId="2" PhysicalOp="Sort" LogicalOp="TopN Sort" EstimateRows="1" EstimateIO="163.119" EstimateCPU="29.7123" AvgRowSize="86" EstimatedTotalSubtreeCost="226.399" Parallel="0" EstimateRebinds="0" EstimateRewinds="0"><OutputList><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Id"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPFrom"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPTo"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryCode"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryName"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Region"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="City"/></OutputList><MemoryFractions Input="0" Output="0"/><TopSort Distinct="0" Rows="1"><OrderBy><OrderByColumn Ascending="1"><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPTo"/></OrderByColumn></OrderBy><RelOp NodeId="3" PhysicalOp="Clustered Index Scan" LogicalOp="Clustered Index Scan" EstimateRows="1.02843e+006" EstimateIO="28.1505" EstimateCPU="3.77105" AvgRowSize="86" EstimatedTotalSubtreeCost="31.9216" Parallel="0" EstimateRebinds="0" EstimateRewinds="0"><OutputList><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Id"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPFrom"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPTo"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryCode"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryName"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Region"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="City"/></OutputList><IndexScan Ordered="0" ForcedIndex="0" NoExpandHint="0"><DefinedValues><DefinedValue><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Id"/></DefinedValue><DefinedValue><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPFrom"/></DefinedValue><DefinedValue><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPTo"/></DefinedValue><DefinedValue><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryCode"/></DefinedValue><DefinedValue><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryName"/></DefinedValue><DefinedValue><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Region"/></DefinedValue><DefinedValue><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="City"/></DefinedValue></DefinedValues><Object Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Index="[PK_tbl_IP2]" TableReferenceId="1"/><Predicate><ScalarOperator ScalarString="[@ip]&lt;=[RecruitmentIP].[dbo].[tbl_IP].[IPTo]"><Compare CompareOp="LE"><ScalarOperator><Identifier><ColumnReference Column="@ip"/></Identifier></ScalarOperator><ScalarOperator><Identifier><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPTo"/></Identifier></ScalarOperator></Compare></ScalarOperator></Predicate></IndexScan></RelOp></TopSort></RelOp><Predicate><ScalarOperator ScalarString="[RecruitmentIP].[dbo].[tbl_IP].[IPFrom]&lt;=[@ip]"><Compare CompareOp="LE"><ScalarOperator><Identifier><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPFrom"/></Identifier></ScalarOperator><ScalarOperator><Identifier><ColumnReference Column="@ip"/></Identifier></ScalarOperator></Compare></ScalarOperator></Predicate></Filter></RelOp><RelOp NodeId="5" PhysicalOp="Filter" LogicalOp="Filter" EstimateRows="1" EstimateIO="0" EstimateCPU="4.8e-007" AvgRowSize="86" EstimatedTotalSubtreeCost="0.00985397" Parallel="0" EstimateRebinds="0" EstimateRewinds="0"><OutputList><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Id"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPFrom"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPTo"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryCode"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryName"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Region"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="City"/></OutputList><Filter StartupExpression="0"><RelOp NodeId="6" PhysicalOp="Top" LogicalOp="Top" EstimateRows="1" EstimateIO="0" EstimateCPU="1e-007" AvgRowSize="86" EstimatedTotalSubtreeCost="0.00985349" Parallel="0" EstimateRebinds="0" EstimateRewinds="0"><OutputList><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Id"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPFrom"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPTo"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryCode"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryName"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Region"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="City"/></OutputList><Top RowCount="0" IsPercent="0" WithTies="0"><TopExpression><ScalarOperator ScalarString="(1)"><Const ConstValue="(1)"/></ScalarOperator></TopExpression><RelOp NodeId="7" PhysicalOp="Nested Loops" LogicalOp="Inner Join" EstimateRows="1" EstimateIO="0" EstimateCPU="4.29882" AvgRowSize="86" EstimatedTotalSubtreeCost="0.00985339" Parallel="0" EstimateRebinds="0" EstimateRewinds="0"><OutputList><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Id"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPFrom"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPTo"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryCode"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryName"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Region"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="City"/></OutputList><NestedLoops Optimized="0" WithOrderedPrefetch="1"><OuterReferences><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Id"/><ColumnReference Column="Expr1006"/></OuterReferences><RelOp NodeId="9" PhysicalOp="Index Seek" LogicalOp="Index Seek" EstimateRows="1" EstimateIO="2.45201" EstimateCPU="1.13142" AvgRowSize="27" EstimatedTotalSubtreeCost="0.0032831" Parallel="0" EstimateRebinds="0" EstimateRewinds="0"><OutputList><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Id"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPFrom"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPTo"/></OutputList><IndexScan Ordered="1" ScanDirection="BACKWARD" ForcedIndex="0" NoExpandHint="0"><DefinedValues><DefinedValue><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Id"/></DefinedValue><DefinedValue><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPFrom"/></DefinedValue><DefinedValue><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPTo"/></DefinedValue></DefinedValues><Object Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Index="[idx_ipfrom_ipto]" TableReferenceId="2"/><SeekPredicates><SeekPredicate><EndRange ScanType="LE"><RangeColumns><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPFrom"/></RangeColumns><RangeExpressions><ScalarOperator ScalarString="[@ip]"><Identifier><ColumnReference Column="@ip"/></Identifier></ScalarOperator></RangeExpressions></EndRange></SeekPredicate></SeekPredicates></IndexScan></RelOp><RelOp NodeId="11" PhysicalOp="Clustered Index Seek" LogicalOp="Clustered Index Seek" EstimateRows="1" EstimateIO="0.003125" EstimateCPU="0.0001581" AvgRowSize="373" EstimatedTotalSubtreeCost="0.00669221" Parallel="0" EstimateRebinds="1" EstimateRewinds="0.797604"><OutputList><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryCode"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryName"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Region"/><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="City"/></OutputList><IndexScan Lookup="1" Ordered="1" ScanDirection="FORWARD" ForcedIndex="0" NoExpandHint="0"><DefinedValues><DefinedValue><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryCode"/></DefinedValue><DefinedValue><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="CountryName"/></DefinedValue><DefinedValue><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Region"/></DefinedValue><DefinedValue><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="City"/></DefinedValue></DefinedValues><Object Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Index="[PK_tbl_IP2]" TableReferenceId="-1"/><SeekPredicates><SeekPredicate><Prefix ScanType="EQ"><RangeColumns><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Id"/></RangeColumns><RangeExpressions><ScalarOperator ScalarString="[RecruitmentIP].[dbo].[tbl_IP].[Id]"><Identifier><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="Id"/></Identifier></ScalarOperator></RangeExpressions></Prefix></SeekPredicate></SeekPredicates></IndexScan></RelOp></NestedLoops></RelOp></Top></RelOp><Predicate><ScalarOperator ScalarString="[RecruitmentIP].[dbo].[tbl_IP].[IPTo]&gt;=[@ip]"><Compare CompareOp="GE"><ScalarOperator><Identifier><ColumnReference Database="[RecruitmentIP]" Schema="[dbo]" Table="[tbl_IP]" Column="IPTo"/></Identifier></ScalarOperator><ScalarOperator><Identifier><ColumnReference Column="@ip"/></Identifier></ScalarOperator></Compare></ScalarOperator></Predicate></Filter></RelOp></NestedLoops></RelOp></QueryPlan></StmtSimple><StmtSimple StatementText="&#xa;set statistics time off" StatementId="4" StatementCompId="4" StatementType="SET STATS"/></Statements></Batch></BatchSequence></ShowPlanXML>

I think the main reason why the query is slow even with index ipfrom, ipto is that the engine can not use the index properly. 我认为即使使用索引ipfrom,查询速度很慢的主要原因,ipto是引擎无法正确使用索引。

It takes the first condition ipfrom <= @ip and is able to use index for that, however this inequality has a low selection and if your ip ranges cover all ips and are not overlapping then for the index has only one ipto entry for each ipfrom index leaf. 它需要第一个条件ipfrom <= @ip并能够使用索引,但是这个不等式的选择很少,如果你的ip范围覆盖所有的ips并且没有重叠,那么索引只有一个ipto条目用于每个ipfrom索引叶。

That is not so useful and it ends up doing full index scan (assumption1). 这不是那么有用,它最终会进行全索引扫描(假设1)。

So, to speed it up there are several tricks 所以,为了加快速度,有几个技巧

1) If select @ip_max_delta = max(ipto-ipfrom) is not to big (~1000 records) you can add WHERE ipfrom > (@ip - @ip_max_delta) (this is directly usable only if ip's are stored as int). 1)如果select @ip_max_delta = max(ipto-ipfrom)不大(~1000条记录),你可以添加WHERE ipfrom > (@ip - @ip_max_delta) (只有当ip存储为int时才可以直接使用)。 This will work well with any index starting with ipfrom 这适用于以ipfrom开头的任何索引

2) 2)

SELECT TOP 1 id, ipfrom, ipto, countrycode, countryname,region,city
FROM tbl_ip 
WHERE ipfrom <= @ip
ORDER BY ipfrom DESC

This should return really quickly (especially if you cluster on ipfrom and you should as your data rarely changes). 这应该很快返回(特别是如果你在ipfrom上集群,你应该因为你的数据很少改变)。

If the above does not return quickly can you test the execution time (and plan) on the following query, just for reference 如果上面没有快速返回,您可以测试以下查询的执行时间(和计划),仅供参考

SELECT id, ipfrom, ipto, countrycode, countryname,region,city
FROM tbl_ip 
WHERE ipfrom = @ip

(choose existing @ip that exists in ipfrom column) (选择ipfrom列中存在的现有@ip)

EDIT2 : Re Martin's solution EDIT2 :Re Martin的解决方案

I don't see reason to a) use intersection/subquery and b) to maintain two indexes 我没有理由a)使用intersection / subquery和b)维护两个索引

SELECT TOP 1 id, ipfrom, ipto, countrycode, countryname,region,city
FROM tbl_ip 
WHERE ipfrom <= @ip
ORDER BY ipfrom DESC

Should return the same as Martin's query if there is correlation between ipfrom and ipto in consecutive rows. 如果在连续行中ipfrom和ipto之间存在相关性,则应返回与Martin的查询相同的内容。 If not then additional condition can be applied directly 如果没有,则可以直接应用附加条件

SELECT TOP 1 id, ipfrom, ipto, countrycode, countryname,region,city
FROM tbl_ip 
WHERE ipfrom <= @ip AND @ip <= ipto
ORDER BY ipfrom DESC

This query is quite similar to the starting one, but the ORDER BY should allow parser to choose better plan (unverfied). 此查询与起始查询非常相似,但ORDER BY应允许解析器选择更好的计划(未经验证)。 If it does not then 如果没有那么

SELECT id, ipfrom, ipto, countrycode, countryname,region,city
FROM
(SELECT TOP 1 id, ipfrom, ipto, countrycode, countryname,region,city
FROM tbl_ip 
WHERE ipfrom <= @ip
ORDER BY ipfrom DESC) s
WHERE @ip <= ipto

Should do the trick and would require only index on ipfrom. 应该做的伎俩,只需要ipfrom索引。

How does this perform? 这是如何表现的? I'm hoping that it should use an index seek on ipto to quickly resolve the top part, an index seek on ipfrom to resolve the bottom part and 2 (or possibly one) bookmark lookups to get the rest of the columns to return. 我希望它应该使用ipto上的索引查找来快速解析顶部,索引寻求ipfrom来解析底部和2(或可能是一个)书签查找以使其余的列返回。

SELECT id, ipfrom, ipto, countrycode, countryname,region,city FROM
(
SELECT TOP 1 id, ipfrom, ipto, countrycode, countryname,region,city
FROM tbl_ip 
WHERE @ip <= ipto
ORDER BY ipto
INTERSECT
SELECT TOP 1 id, ipfrom, ipto, countrycode, countryname,region,city
FROM tbl_ip 
WHERE ipfrom <= @ip
ORDER BY ipfrom DESC
) ip

尝试将此添加到WHERE子句AND ipfrom <= ipto

Is your clustered index on id? 你的聚集索引是id吗? If so, you could maybe change it to ipfrom, ipto. 如果是这样,您可以将其更改为ipfrom,ipto。

there is a more simple and logical solution: 有一个更简单和合理的解决方案:

1) create an extra column in your ip_country table: Arange which is actually ip_from / 16777216 1)在ip_country表中创建一个额外的列:Arange,实际上是ip_from / 16777216

2) create a clustered index on Arange, ip_from 2)在Arange,ip_from上创建聚簇索引

3) use "[ipaddress]/16777216 =Arange and [ipaddress] between ip_from and ip_to" in your query 3)在查询中使用“[ipaddress] / 16777216 = Arange和[ipaddress]之间的ip_from和ip_to”

What are your indexes? 你的索引是什么? Would it help if you had one covering index? 如果你有一个覆盖指数会有帮助吗? So ipfrom, ipto on one index? 所以ipfrom,ipto在一个索引上? Could then even "include" id, countrycode, countryname, region, and city fields in that index so system does not have to go to data pages to get that data. 然后甚至可以在该索引中“包含”id,countrycode,countryname,region和city字段,这样系统就不必转到数据页来获取该数据。

-Krip -Krip

I see two ways to reduce execution time 我看到两种减少执行时间的方法

1.Simple one would be to Cache whole 3m of records and use .NET native Datasets to retrieve wanted item in IP range. 1.简单的一个是缓存整个3米的记录并使用.NET原生数据​​集来检索IP范围内的所需项目。 This will obviously eat your server CPU but you won't make 10 calls to DB every second. 这显然会占用你的服务器CPU,但你不会每秒对DB进行10次调用。

2.Harder one would be to split IPs to different tables like IPRanges1 .... IPRanges9. 2.Harder one将IP分割到不同的表,如IPRanges1 .... IPRanges9。 So once you get user IP and want to query other details, you just pass to query another param with first digit of IP. 因此,一旦您获得用户IP并想要查询其他详细信息,您只需传递查询另一个具有IP的第一个数字的参数。 This will reduce looping through 3M to 3m/9 (or something like that). 这将减少通过3M的循环到3m / 9(或类似的东西)。 Reduce in execution time will be obvious. 减少执行时间将是显而易见的。 If you combine it with Caching method you will end up with something proper. 如果将它与缓存方法结合使用,您将得到适当的结果。

If ip ranges start at powers of 2 (and they should), you could exploit the fact that ip = ipfrom or ip = ipfrom & 11...10 or ip = ipfrom & 11...00, etc... 如果ip范围从2的幂开始(他们应该),你可以利用ip = ipfrom或ip = ipfrom&11 ... 10或ip = ipfrom&11 ... 00等事实......

32 index lookups should be faster than a index range scan. 32个索引查找应该比索引范围扫描更快。

Just a thought. 只是一个想法。

如果您确定结果数据只是一行,那么您可以使用ForceSeek选项

May be review possibility to change architecture? 可能会审查改变架构的可能性? (Using MSSQL hints me that you can use .Net) Since you use readonly database review some: in memory database. (使用MSSQL提示我你可以使用.Net)因为你使用readonly数据库审查一些:在内存数据库中。 Or try OracleCoherence for .Net ( http://coherence.oracle.com/ ) 或者尝试使用OracleCoherence for .Net( http://coherence.oracle.com/

You probably need to separate out the data into two tables: IPData (ipfrom, ipto, locationid) and LocationData (locationid, countryname, city, etc) 您可能需要将数据分成两个表:IPData(ipfrom,ipto,locationid)和LocationData(locationid,countryname,city等)

I would change the where clause to: 我会将where子句更改为:

WHERE @ip BETWEEN ipfrom AND ipto

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM