Limit query size for specific users - oracle

Is there a way to limit the rows returned for a user in Oracle.
We have some users than can query some tables with millions of records decreasing the performance of the database, so I would like to know if there someway to set max size of records per user.
For example, If I have the table: APP.HISTORY with 10,000,000 records and the user 'dummy', I would like to set for dummy user that can only read 10,000 records from it.
For example if 'dummy' execute:
select * from APP.HISTORY
It will only return 10,000 records, instead try to fetch the 10,000,000 records

There isn't any built-in functionality to limit the number of results per user.
However, even if you could, that wouldn't necessarily help you resolve your performance concern.
Consider for example a query like:
select *
from (select *
from app.history
order by some_field desc)
where rownum < 2
According to your requirements, user dummy would be able to run this and get back the single result he's interested in. However, assuming some_field is not indexed, then, even though this query will return a single record, it still has to order all 10,000,000 records to produce that single row.
As suggested by OldProgrammer in the comments, consider using resource groups, which is a very flexible and configurable way of throttling CPU and I/O usage.
Otherwise, if you don't trust user dummy to write smart and efficient queries, then don't give him direct access to the database.

Related

Get Status Statistics from enumerated column JPA CrudRepository H2

I have a table with an enumerated column named "status". I am implementing an endpoint to get statistics about active and inactive entries. It will return a response like this
{ "activeCount" : 10, "inactiveCount" : 10 }
There are 4 possible status for each entry (active, inactive, awaitingApproval, suspicious). activeCount = amount of entries with active status.
inactiveCount = amount of entries with inactive/awaitingApproval/suspicious status.
I am using controller-service-repository pattern and H2 in-memory database. I need this to be as fast as possible. Also assume that this table will hold massive amount of data in the future so getting all entries into memory and calculating the status statistics is not possible.
What are your best practice suggestions?
Thanks for help in advance.
Just use a query like select e.status, count(*) from Entity e group by e.status. If this is not fast enough for you, you will have to maintain a current count per group somehow in a dedicated table and just query that. That obviously requires you to change the count respectively for every status change or insert/delete. Usually, this can be done by using triggers.

Scan on DynamDB table or Query on secondary global index or a local index (What's the best solution)

I have AWS DynamoDB table called "Users", whose hash key/primary key is "UserID" which consist of emails. It has two attributes, first called "Daily Points" and second "TimeSpendInTheApp". Now I need to run a query or scan on the table, that will give me top 50 users which have the highest points and top 50 users which have spend the most time in the app. Now this query will be executed only once a day by cron aws lambda. I am trying to find the best solutions for this query or scan. For me, the cost is most important than speed/or efficiency. As maintaining secondary global index or a local index on points can be costly operations, as I have to assign Read and Write units for those indexes, which I want to avoid. "Users" table will have a maximum of 100,000 to 150,000 records and on average it will have 50,000 records. What are my best options? Please suggest.
I am thinking, my first option is, I can scan the whole table on Filter Expression for records above certain points (5000 for example), after this scan, if 50 or more than 50 records are found, then simply sort the values and take the top 50 records. If this scan returns no or very less results then reduce the Filter Expression value (3000 for example), then again do the same scan operation. If Filter Expression value (2500 for example) returns too many records, like 5000 or more, then reduce the Filter Expression value. Is this even possible, I guess it would also need to handle pagination. Is it advisable to scan on a table which has 50,000 record?
Any advice or suggestion will be helpful. Thanks in advance.
Firstly, creating indexes for the above use case doesn't simplify the process as it doesn't have solution for aggregation or sorting.
I would export the data to HIVE and run the queries rather than writing code to determine the result especially as it is going to be a batch executed only once per day.
Something like below:-
Create Hive table:-
CREATE EXTERNAL TABLE hive_users(userId string, dailyPoints bigint, timeSpendInTheApp bigint)
STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler'
TBLPROPERTIES ("dynamodb.table.name" = "Users",
"dynamodb.column.mapping" = "userId:UserID,dailyPoints:Daily_Points,timeSpendInTheApp:TimeSpendInTheApp");
Queries:-
SELECT dailyPoints, userId from hive_users sort by dailyPoints desc;
SELECT timeSpendInTheApp, userId from hive_users sort by timeSpendInTheApp desc;
Hive Reference

Access - Get the total of a column in a select query

I have an Access database set up that takes a bunch of raw data, splits things up in different 'select' queries and pipes the results into various CSV files, where a dashboard set up in Excel will pick it up.
There's some data that I'm trying to calculate in Access, namely I have a quantity field, and I need to calculate the percentage of for each record. In other words, quantity / total of quantity.
Using my rather limited Access abilities, I tried the following query:
SELECT [Sales].*, [Quantity] / Sum([Quantity]) AS QuantityPercent FROM [Sales];
Which comes up with an error:
Your query does not include the specified expression 'company_name' as part of an aggregate function.
Company_name is the first field of the table, and after some Googling and Binging, I'm still quite confused as to what it means in this context.
To sum it up, my question is this: Is there a way to calculate data based off the total of a column/field?
The easy method is to use DSum:
SELECT
[Sales].*,
[Quantity] / DSum("[Quantity]", "[Sales]") AS QuantityPercent
FROM
[Sales];

VisitorID in BigQuery doesn't match Sessions Google Analytics

I've looked around the web and I keep getting the same answer: to count sessions in BigQuery, take count(distinct concat(fullvisitorID, string(visitID))). But in some cases, that's not even getting me close to the sessions in Google Analytics. Is there any other way to count sessions better? Here's what I'm trying to do:
SELECT hits.customdimensions.value val,
count(*) as pageviews,
exact_count_distinct(CONCAT([fullVisitorId], STRING([visitid]))) sessions
FROM [xxx.ga_sessions_20150619]
where hits.customdimensions.index = 7 and lower(hits.type) = 'page'
group by val
order by pageviews desc
LIMIT 1000
For some custom dimension values, that gets close to GA, but others are off by twice the amount. Is there any way to get a better session count in BQ?
Well, I can't really speak to your GA data itself (of course, check to make sure you're not sampling the data at all), but if you run the following query, you'll pull the sum of each of the session counts per fullVisitorId:
SELECT SUM(sessionsPerUser)
FROM (SELECT fullVisitorId, COUNT(visitNumber) AS sessionsPerUser
FROM [xxx.ga_sessions_2017yyzz]
GROUP BY fullVisitorId)

Is it a good idea to store and access an active query resultset in Coldfusion vs re-quering the database?

I have a product search engine using Coldfusion8 and MySQL 5.0.88
The product search has two display modes: Multiple View and Single View.
Multiple displays basic record info, Single requires additional data to be polled from the database.
Right now a user does a search and I'm polling the database for
(a) total records and
(b) records FROM to TO.
The user always goes to Single view from his current resultset, so my idea was to store the current resultset for each user and not have to query the database again to get (waste a) overall number of records and (waste b) a the single record I already queried before AND then getting the detail information I still need for the Single view.
However, I'm getting nowhere with this.
I cannot cache the current resultset-query, because it's unique to each user(session).
The queries are running inside a CFINVOKED method inside a CFC I'm calling through AJAX, so the whole query runs and afterwards the CFC and CFINVOKE method are discarded, so I can't use query of query or variables.cfc_storage.
So my idea was to store the current resultset in the Session scope, which will be updated with every new search, the user runs (either pagination or completely new search). The maximum results stored will be the number of results displayed.
I can store the query allright, using:
<cfset Session.resultset = query_name>
This stores the whole query with results, like so:
query
CACHED: false
EXECUTIONTIME: 2031
SQL: SELECT a.*, p.ek, p.vk, p.x, p.y
FROM arts a
LEFT JOIN p ON
...
LEFT JOIN f ON
...
WHERE a.aktiv = "ja"
AND
... 20 conditions ...
SQLPARAMETERS: [array]
1) ... 20+ parameters
RESULTSET:
[Record # 1]
a: true
style: 402
price: 2.3
currency: CHF
...
[Record # 2]
a: true
style: 402abc
...
This would be overwritten every time a user does a new search. However, if a user wants to see the details of one of these items, I don't need to query (total number of records & get one record) if I can access the record I need from my temp storage. This way I would save two database trips worth 2031 execution time each to get data which I already pulled before.
The tradeoff would be every user having a resultset of up to 48 results (max number of items per page) in Session.scope.
My questions:
1. Is this feasable or should I requery the database?
2. If I have a struture/array/object like a the above, how do I pick the record I need out of it by style number = how do I access the resultset? I can't just loop over the stored query (tried this for a while now...).
Thanks for help!
KISS rule. Just re-query the database unless you find the performance is really an issue. With the correct index, it should scales pretty well. When the it is an issue, you can simply add query cache there.
QoQ would introduce overhead (on the CF side, memory & computation), and might return stale data (where the query in session is older than the one on DB). I only use QoQ when the same query is used on the same view, but not throughout a Session time span.
Feasible? Yes, depending on how many users and how much data this stores in memory, it's probably much better than going to the DB again.
It seems like the best way to get the single record you want is a query of query. In CF you can create another query that uses an existing query as it's data source. It would look like this:
<cfquery name="subQuery" dbtype="query">
SELECT *
FROM Session.resultset
WHERE style = #SelectedStyleVariable#
</cfquery>
note that if you are using CFBuilder, it will probably scream Error at you for not having a datasource, this is a bug in CFBuilder, you are not required to have a datasource if your DBType is "query"
Depending on how many records, what I would do is have the detail data stored in application scope as a structure where the ID is the key. Something like:
APPLICATION.products[product_id].product_name
.product_price
.product_attribute
Then you would really only need to query for the ID of the item on demand.
And to improve the "on demand" query, you have at least two "in code" options:
1. A query of query, where you query the entire collection of items once, and then query from that for the data you need.
2. Verity or SOLR to index everything and then you'd only have to query for everything when refreshing your search collection. That would be tons faster than doing all the joins for every single query.

Resources