Skip to content
This repository was archived by the owner on May 12, 2021. It is now read-only.

Conversation

@RajashekharChoukimath
Copy link

@RajashekharChoukimath RajashekharChoukimath commented Jul 3, 2019

Fixed following Issues in Lens for Azure Migrations

  1. Bug in Lens-Metastore for single fact granularity -- https://issues.apache.org/jira/browse/LENS-1544. Explaination: This had a special case for handling facts with one-update-period and multiple-update-periods. The case which handled one-update-period had a bug while generating the name of the hive table whole format is update_period-fact_name, the update_period was coming as null.
  2. JDBCDriver.java was invoking JDBC Driver while validating the prepared query, I don't need this functionality so blocking this via already existing config parameter JDBC_VALIDATE_THROUGH_PREPARE.
    2a) Old Flow:
    esitmate()
    --- | --> validate
    -----| --> JDBC_VALIDATE_THROUGH_PREPARE condition to prepare through if condition
    -----|--> prepareInternal()
    ----------------|--> rewrite -- Rewritting take place
    2b) New Flow:
    esitmate()
    ---| --> rewrite -- Rewritting take place
    ---| --> validate
    -----| --> JDBC_VALIDATE_THROUGH_PREPARE condition to prepare through if condition
    -----|--> prepareInternal()
    2c) JDBC_VALIDATE_THROUGH_PREPARE has been renamed as JDBC_VALIDATE_THROUGH_PREPARE_OR_EXPLAIN, because even explain makes JDBC call to the underlying JDBCDriver, so used this variable to stop it from calling underlying JDBCDriver.

File level explainations:

  1. CubeMetastoreClient.java -- This had a special case for handling facts with one-update-period and multiple-update-periods. The case which handled one-update-period had a bug while generating the name of the hive table whole format is update_period-fact_name, the update_period was coming as null.
  2. JDBCDriver.java -- This was trying to invoke the underlying JDBC Driver while validating the prepared query, I have moved it up into the estimate() method
  3. TestJDBCDriver.java -- related to item 2.
  4. PreparedQueryContext.java -- We want to store the prepared query into the DB similar to finished_queries, so added start and end times. Also used these fields to measure the time lens takes to prepare the query. Related to item 5
  5. LensServerDAO.java -- We want to store the prepared query into the DB similar to finished_queries, so we created a new table called prepared_queries and added the cube and driver query into it.
  6. QueryExecutionServiceImpl.java --
    6a) Related to item 5. -- Inserting the prepared Query and time difference.
    6b) also removed the line prepared.getSelectedDriver().prepare(prepared); because this was already taken care in prepareQuery(sessionHandle, query, lensConf, SubmitOp.PREPARE);

@Amareshwari
Copy link
Contributor

@RajashekharChoukimath Can you create corresponding jira and update pull request summary with jira id?

@guptapuneet
Copy link
Contributor

@RajashekharChoukimath can you please remove the internal JIRA details from description.

@RajashekharChoukimath
Copy link
Author

RajashekharChoukimath commented Jul 8, 2019 via email

@RajashekharChoukimath RajashekharChoukimath changed the title Fixed Issues in Lens for Azure Migrations Fixed a Bug and made changes for PreparedQuery. Jul 9, 2019
@RajashekharChoukimath RajashekharChoukimath changed the title Fixed a Bug and made changes for PreparedQuery. [LENS-1545]: Fixed a Bug and made changes for PreparedQuery. Jul 9, 2019

return result;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add update prepare query also

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't update the prepared query, we insert only prepared query, so it is not needed.

* @param preparedQueryContext to be inserted
* @throws SQLException the exception
*/
public void insertPreparedQuery(PreparedQueryContext preparedQueryContext) throws SQLException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add unit tests

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a void method, and anyways it calls external system to insert data, I don't think we should be unit-testing here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am asking or unit test around new snippet of code written here and unit test is not only around return value.
Consider a scenario where in future any user wants to use this function and end up calling "insert prepare" twice from his code then this code is expected throw exception in the second call. A developer will not come to know this at build time unless unit tests are added. There can be many such scenarios unknown now.
Also please add checks and unit tests for invalid values of preparedQueryContext. It can cause runtime exception. rethrow LensException instead.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some one calling once/twice/zero times is not part of unit testing. It is a overkill to unnecessarily mock and unit test.
In this code snippet, it is making a call to a external system and it returns void.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

anyways I have added unit test case.

prepared = prepareQuery(sessionHandle, query, lensConf, SubmitOp.PREPARE);
prepared.setQueryName(queryName);
prepared.getSelectedDriver().prepare(prepared);
try {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

push start time and end time for prepared query in db and emit metric for query prepare time.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the prepared query, I am inserting start_time and timeTaken(this can deduce the end_time if needed).
Regarding the NumberOfPrepared queries, it is already being emitted PREPARED_QUERIES_COUNTER. Regarding the query prepare time is already present in database.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume we are capturing query prepare time for lens query to monitor its performance. If that's the case its always better to emit metric that indicates average prepare query time over last 5 mins, 60 min, etc. PREPARED_QUERIES_COUNTER is different counter I am asking you to emit one for prepare time with aggregation that can be used to raise an alert. To monitor performance by looking into db is not good practice. It is being used mostly for bookkeeping.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is already happening. All the public methods of QueryServiceResource histograms are already pushed by default.

// Only create a prepared statement and then close it
MethodMetricsContext sqlRewriteGauge = MethodMetricsFactory.createMethodGauge(pContext.getDriverConf(this), true,
metricCallStack + COLUMNAR_SQL_REWRITE_GAUGE);
String rewrittenQuery = rewriteQuery(pContext);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rewrite query is called for estimate, prepare, explain etc. In this case estimate will work fine. explain will fail to initialize "String rewrittenQuery" since rewriteQuery was never called and pContext.getSelectedDriverQuery(); will be null.
Exsisting unit test must have failed for this scenario. Please run unit tests.
Also I wouldnt recoomend this approach since we have to call rewrite for estimate/prepare/explaing etc.
Please make it config driven in estimate call.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Explain also works fine because of the below stack trace:
JDBCDriver.rewriteQuery(AbstractQueryContext) line: 529
JDBCDriver.explain(AbstractQueryContext) line: 582
QueryExecutionServiceImpl.explain(String, LensSessionHandle, String, LensConf) line: 3141

Explain was also try to make JDBC connection, I have stopped this using JDBC_VALIDATE_THROUGH_PREPARE(I have renamed this variable to JDBC_VALIDATE_THROUGH_PREPARE_OR_EXPLAIN).

prepared = prepareQuery(sessionHandle, query, lensConf, SubmitOp.PREPARE);
prepared.setQueryName(queryName);
prepared.getSelectedDriver().prepare(prepared);
try {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume we are capturing query prepare time for lens query to monitor its performance. If that's the case its always better to emit metric that indicates average prepare query time over last 5 mins, 60 min, etc. PREPARED_QUERIES_COUNTER is different counter I am asking you to emit one for prepare time with aggregation that can be used to raise an alert. To monitor performance by looking into db is not good practice. It is being used mostly for bookkeeping.

* @param preparedQueryContext to be inserted
* @throws SQLException the exception
*/
public void insertPreparedQuery(PreparedQueryContext preparedQueryContext) throws SQLException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am asking or unit test around new snippet of code written here and unit test is not only around return value.
Consider a scenario where in future any user wants to use this function and end up calling "insert prepare" twice from his code then this code is expected throw exception in the second call. A developer will not come to know this at build time unless unit tests are added. There can be many such scenarios unknown now.
Also please add checks and unit tests for invalid values of preparedQueryContext. It can cause runtime exception. rethrow LensException instead.

try {
lensServerDao.insertPreparedQuery(prepared);
} catch (Exception e) {
incrCounter(PREPARED_QUERY_INSERT_COUNTER);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a failed counter? Also why is exception eaten up?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the counter name was wrong, i have renamed it to PREPARED_QUERY_INSERT_ERROR_COUNTER and also throwed the exception.

for (Map.Entry entry : updatePeriodToTableMap.entrySet()) {
XUpdatePeriodTableDescriptor updatePeriodTableDescriptor = new XUpdatePeriodTableDescriptor();
updatePeriodTableDescriptor.setTableDesc(getStorageTableDescFromHiveTable(
XStorageTableElement tblElement = new XStorageTableElement();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can a unit test be added for the bug fixed here?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added it.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

@Amareshwari Amareshwari merged commit 4907964 into apache:master Jul 24, 2019
RajashekharInmobi added a commit to RajashekharInmobi/lens that referenced this pull request Aug 13, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants