如何改进具有 700 万行的 table 的本机查询?
How can I improve the native query for a table with 7 millions rows?
我的数据库(SQL 服务器)中有以下视图(table)。
我想从这个 table 中检索 2 个东西。
- 具有每个产品编号的最晚预订日期的对象。
它将 return 对象 = {0001, 2, 2019-06-06 10:39:58} 和 {0003, 2, 2019-06-07 12:39:58}。
- 如果所有步数都没有产品编号的预订日期,它将return步数= 1的对象。它将return对象= {0002, 1, NULL }.
视图有 7.000.000 行。我必须使用本机查询来完成。
检索具有最新预订日期的产品的第一个查询:
SELECT DISTINCT *
FROM TABLE t
WHERE t.BOOKING_DATE = (SELECT max(tbl.BOOKING_DATE) FROM TABLE tbl WHERE t.PRODUCT_NUMBER = tbl.PRODUCT_NUMBER)
第二个查询检索预订日期为 NULL 且步数 = 1 的产品;
SELECT DISTINCT *
FROM TABLE t
WHERE (SELECT max(tbl.BOOKING_DATE) FROM TABLE tbl WHERE t.PRODUCT_NUMBER = tbl.PRODUCT_NUMBER) IS NULL AND t.STEP_NUMBER = 1
我尝试使用单个查询,但它花费的时间太长。
现在我使用 2 查询来获取这些信息,但为了将来我需要改进它。你有其他选择吗?我也不能使用SQL SERVER里面的存储过程,函数。我必须使用来自 Java 的本机查询来完成它。
尝试 row_number()
正确排序。 sql-server ORDER BY.
将 Null 值视为可能的最低值
SELECT TOP(1) WITH TIES *
FROM myTable t
ORDER BY row_number() over(partition by PRODUCT_NUMBER order by BOOKING_DATE DESC, STEP_NUMBER);
注意 sql- 服务器建议的索引以获得良好的性能。
试试这个,
Declare @p table(pumber int,step int,bookdate datetime)
insert into @p values
(1,1,'2019-01-01'),(1,2,'2019-01-02'),(1,3,'2019-01-03')
,(2,1,null),(2,2,null),(2,3,null)
,(3,1,null),(3,2,null),(3,3,'2019-01-03')
;With CTE as
(
select pumber,max(bookdate)bookdate
from @p p1
where bookdate is not null
group by pumber
)
select p.* from @p p
where exists(select 1 from CTE c
where p.pumber=c.pumber and p.bookdate=c.bookdate)
union all
select p1.* from @p p1
where p1.bookdate is null and step=1
and not exists(select 1 from CTE c
where p1.pumber=c.pumber)
如果性能是主要关注点,那么 1 次或 2 次查询都无所谓,最后性能很重要。
Create NonClustered index ix_Product on Product (ProductNumber,BookingDate,Stepnumber)
Go
如果超过 90% 的数据是 where BookingDate is not null
或 where BookingDate is null
,那么您可以在其上创建过滤索引。
Create NonClustered index ix_Product on Product (ProductNumber,BookingDate,Stepnumber)
where BookingDate is not null
Go
可能最有效的方法是相关子查询:
select t.*
from t
where t.step_number = (select top (1) t2.step_number
from t t2
where t2.product_number = t.product_number and
order by t2.booking_date desc, t2.step_number
);
特别是,这可以利用 (product_number, booking_date desc, step_number)
上的索引。
我的数据库(SQL 服务器)中有以下视图(table)。
我想从这个 table 中检索 2 个东西。
- 具有每个产品编号的最晚预订日期的对象。 它将 return 对象 = {0001, 2, 2019-06-06 10:39:58} 和 {0003, 2, 2019-06-07 12:39:58}。
- 如果所有步数都没有产品编号的预订日期,它将return步数= 1的对象。它将return对象= {0002, 1, NULL }.
视图有 7.000.000 行。我必须使用本机查询来完成。
检索具有最新预订日期的产品的第一个查询:
SELECT DISTINCT *
FROM TABLE t
WHERE t.BOOKING_DATE = (SELECT max(tbl.BOOKING_DATE) FROM TABLE tbl WHERE t.PRODUCT_NUMBER = tbl.PRODUCT_NUMBER)
第二个查询检索预订日期为 NULL 且步数 = 1 的产品;
SELECT DISTINCT *
FROM TABLE t
WHERE (SELECT max(tbl.BOOKING_DATE) FROM TABLE tbl WHERE t.PRODUCT_NUMBER = tbl.PRODUCT_NUMBER) IS NULL AND t.STEP_NUMBER = 1
我尝试使用单个查询,但它花费的时间太长。 现在我使用 2 查询来获取这些信息,但为了将来我需要改进它。你有其他选择吗?我也不能使用SQL SERVER里面的存储过程,函数。我必须使用来自 Java 的本机查询来完成它。
尝试 row_number()
正确排序。 sql-server ORDER BY.
SELECT TOP(1) WITH TIES *
FROM myTable t
ORDER BY row_number() over(partition by PRODUCT_NUMBER order by BOOKING_DATE DESC, STEP_NUMBER);
注意 sql- 服务器建议的索引以获得良好的性能。
试试这个,
Declare @p table(pumber int,step int,bookdate datetime)
insert into @p values
(1,1,'2019-01-01'),(1,2,'2019-01-02'),(1,3,'2019-01-03')
,(2,1,null),(2,2,null),(2,3,null)
,(3,1,null),(3,2,null),(3,3,'2019-01-03')
;With CTE as
(
select pumber,max(bookdate)bookdate
from @p p1
where bookdate is not null
group by pumber
)
select p.* from @p p
where exists(select 1 from CTE c
where p.pumber=c.pumber and p.bookdate=c.bookdate)
union all
select p1.* from @p p1
where p1.bookdate is null and step=1
and not exists(select 1 from CTE c
where p1.pumber=c.pumber)
如果性能是主要关注点,那么 1 次或 2 次查询都无所谓,最后性能很重要。
Create NonClustered index ix_Product on Product (ProductNumber,BookingDate,Stepnumber)
Go
如果超过 90% 的数据是 where BookingDate is not null
或 where BookingDate is null
,那么您可以在其上创建过滤索引。
Create NonClustered index ix_Product on Product (ProductNumber,BookingDate,Stepnumber)
where BookingDate is not null
Go
可能最有效的方法是相关子查询:
select t.*
from t
where t.step_number = (select top (1) t2.step_number
from t t2
where t2.product_number = t.product_number and
order by t2.booking_date desc, t2.step_number
);
特别是,这可以利用 (product_number, booking_date desc, step_number)
上的索引。