First, a simple example to describe my problem.
Model
public class User
{
public virtual String UserID { get; set; }
public virtual String UserName { get; set; }
public virtual DateTime LastLoginTime { get; set; }
}
Mapping
<id name="UserID" type="AnsiString">
<column name="p_UserID_vc" length="20"></column>
<generator class="assigned"/>
</id>
<property name="UserName" column="UserName_vc" type="AnsiString">
<property name="LastLoginTime" column="LastLoginTime_d" type="DateTime">
table
create table T_User
(
p_userid_vc VARCHAR2(20) not null,
username_vc VARCHAR2(50),
lastlogintime_d DATE,
)
Now ,there are one million users in this table. I create a oracle index in LastLoginTime. I use query like this:
var list = Responsity<User>.Where(q => q.LastLoginTime <= DateTime.Now &&
q.LastLoginTime >= DateTime.Now.AddDays(-7));
I use Nhibernate Profile to watchout the real sql string:
select t.p_UserID_vc
from T_User t
where t.lastlogintime_d >= TIMESTAMP '2012-03-19 16:58:32.00' /* :p1 */
and t.lastlogintime_d <= TIMESTAMP '2012-03-26 16:58:32.00' /* :p2 */
It didn't use the index. I think it should use 'to_date' ,so that it could use the index. How to config the mapping file?
There are a few reasons why it might not be using your index:
The datatype of LastLoginTime is a DATE, but the parameters are TIMESTAMPs, so it might be implicitly converting the column to a timestamp, which would mean it cannot use the index.
The Cost-Based-Optimizer (CBO) might be using statistics which indicate that using the index would be less efficient than not using it. For example, there might be very few rows in the table, or a histogram might tell the CBO that a large number of rows match the date range you're querying on. It's not uncommon for full table scans to outperform queries that use indexes.
Perhaps the statistics on the table are out-of-date, causing the CBO to make inaccurate estimates.
Do an explain plan on your query to determine what the cause is.
Note: the plan for a query that uses literal values (e.g. TIMESTAMP '...') could very well be different to that for a query that uses bind variables (e.g. p1 and p2). Run the explain plan for the query that is actually being executed.
just in case if anyone is still looking for an answer, hope this helps
the fix is to configure it with proper dialect, in my case it is NHibernate.Dialect.Oracle10gDialect
Related
I'm using JPA CriteriaBuilder to select attributes from the database. I have a specific use case that involves Conversion of datetime to date. The Projection segment of the code is as follows.
CriteriaQuery<ResponseDTO> query = cb.createQuery(ResponseDTO.class);
query.multiselect(root.get(MasterPackagesV1_.masterPackageName),
packageJoin.get(PackagesV1_.packageId),
packageJoin.get(PackagesV1_.packageName),
packageJoin.get(PackagesV1_.startSellingDate),
packageJoin.get(PackagesV1_.endSellingDate),
packageJoin.get(PackagesV1_.createdDate),
packageJoin.get(PackagesV1_.modifiedDate),
packagePaymentJoin.get(PackagePaymentPlanV1_.mrp),
packageSubscriptionJoin.get(PackageSubscriptionsV1_.packageSubscriptionId)
);
All of the date attributes are stored as datetime datatype in the MySQL database. I'm want the datetime to be formatted to date. i.e Instead of retrieving the Dates as LocalDateTime I want it to be converted to LocalDate during Instantiation.
I have made changes in the ResponseDTO class accordingly to support LocalDate. Thanks in Advance.
I'm using EF Core but I'm not really an expert with it, especially when it comes to details like querying tables in a performant manner...
So what I try to do is simply get the max-value of one column from a table with filtered data.
What I have so far is this:
protected override void ReadExistingDBEntry()
{
using Model.ResultContext db = new();
// Filter Tabledata to the Rows relevant to us. the whole Table may contain 0 rows or millions of them
IQueryable<Measurement> dbMeasuringsExisting = db.Measurements
.Where(meas => meas.MeasuringInstanceGuid == Globals.MeasProgInstance.Guid
&& meas.MachineId == DBMatchingItem.Id);
if (dbMeasuringsExisting.Any())
{
// the max value we're interested in. Still dbMeasuringsExisting could contain millions of rows
iMaxMessID = dbMeasuringsExisting.Max(meas => meas.MessID);
}
}
The equivalent SQL to what I want would be something like this.
select max(MessID)
from Measurement
where MeasuringInstanceGuid = Globals.MeasProgInstance.Guid
and MachineId = DBMatchingItem.Id;
While the above code works (it returns the correct value), I think it has a performance issue when the database table is getting larger, because the max filtering is done at the client-side after all rows are transferred, or am I wrong here?
How to do it better? I want the database server to filter my data. Of course I don't want any SQL script ;-)
This can be addressed by typing the return as nullable so that you do not get a returned error and then applying a default value for the int. Alternatively, you can just assign it to a nullable int. Note, the assumption here of an integer return type of the ID. The same principal would apply to a Guid as well.
int MaxMessID = dbMeasuringsExisting.Max(p => (int?)p.MessID) ?? 0;
There is no need for the Any() statement as that causes an additional trip to the database which is not desirable in this case.
I have a cosmos db collection. I need to query all documents and return them in order of creation date. Creation date is a defined field but for historical reason it is in string format as MM/dd/yyyy. For example: 02/09/2019. If I just order by this string, the result is chaos.
I am using linq lambda to write my query in webapi. I have tried to parse the string and try to convert the string. Both returned "method not supported".
Here is my query:
var query = Client.CreateDocumentQuery<MyModel>(CollectionLink)
.Where(f => f.ModelType == typeof(MyModel).Name.ToLower() && f.Language == getMyModelsRequestModel.Language )
.OrderByDescending(f => f.CreationDate)
.AsDocumentQuery();
Appreciate for any advice. Thanks. It will be huge effort to go back and modify the format of the field (which affects many other things). I wish to avoid it if possible.
Chen Wang.Since the order by does not support derived values or sub query(link),so you need to sort the derived values by yourself i think.
You could construct the MM/dd/yyyy to yyyymmdd by UDF in cosmos db.
udf:
function getValue(datetime){
return datetime.substring(6,10)+datetime.substring(0,2)+datetime.substring(3,5);
}
sql:
SELECT udf.getValue(c.time) as time from c
Then you could sort the array by property value of class in c# code.Please follow this case:How to sort an array containing class objects by a property value of a class instance?
I have a secondary index on an optional column:
class Sessions extends CassandraTable[ConcreteSessions, Session] {
object matchId extends LongColumn(this) with PartitionKey[Long]
object userId extends OptionalLongColumn(this) with Index[Option[Long]]
...
}
However, the indexedToQueryColumn implicit conversion is not available for optional columns, so this does not compile:
def getByUserId(userId: Long): Future[Seq[Session]] = {
select.where(_.userId eqs userId).fetch()
}
Neither does this:
select.where(_.userId eqs Some(userId)).fetch()
Or changing the type of the index:
object userId extends OptionalLongColumn(this) with Index[Long]
Is there a way to perform such a query using phantom?
I know that I could denormalize, but it would involve some very messy housekeeping and triple our (substantial) data size. The query usually returns only a handful of results, so I'd be willing to use a secondary index in this case.
Short answer: You could not use optional fields in order to query things in phantom.
Long detailed answer:
But, if you really want to work with secondary optional columns, you should declare your entity field as Option but your phantom representation should not be an option in order to query.
object userId extends LongColumn(this) with Index[Long]
In the fromRow(r: Row) you can create your object like this:
Sessions(matchId(r), Some(userId(r)))
Then in the service part you could do the following:
.value(_.userId, t.userId.getOrElse(0))
You also have a better way to do that. You could duplicate the table, making a new kind of query like sessions_by_user_id where in this table your user_id would be the primary key and the match_id the clustering key.
Since user_id is optional, you would end with a table that contains only valid user ids, which is easy and fast to lookup.
Cassandra relies on queries, so use it in your favor.
Take a look up on my github project that helps you get up with multiple queries in the same table.
https://github.com/iamthiago/cassandra-phantom
In my Oracle database, there is an Agreement table with a column effectivityDate with a data type of DATE. When I try to query a certain row
select * from agreement where id = 'GB'
it returns a row with this value:
id: GB
name: MUITF - Double bypass
...
effectivityDate: 7/2/2015
I created a Grails Domain class for this:
class Agreement implements Serializable {
String id
Date effectivityDate
static mapping = {
table "agreement"
varsion: false
id column: "id"
name column: "name"
...
effectivityDate column: "effectivityDate"
}
}
But when I tried to query it on groovy using:
Agreement a = Agreement.findById("GB")
println a
It return this object:
[id:GB, name:MUITF - Double bypass, ..., effectivityDate: 2015-07-01T16:00:00Z]
^^^^^^^^^^^^^^^^^^^^
My question is, why would the date fetched directly from the database different from the one retrieved by gorm? Does this have something to do with time zones?
Just seen in your profile you are from Philippines (PHT, GMT+8).
Since 2015-07-01T16:00:00Z === 2015-07-02T00:00:00+08:00, the most likely cause is that you are using the PHT time zone to display the date when querying the database and the GMT/Zulu time zone when querying/displaying with groovy/grails.