If I were to take an educated guess, it would be that the query "optimizer" for the first one is favoring the hard-coded adminID for an index. Not knowing your indexes, it may be that this is causing either an index or table scan (my guess is index, but that assumes you have an index on VisitLogID). Keep in mind, the optimizer does not do variable replacement per se, so when it goes to figure out what the fastest plan is to execute, it doesn't know that "@id" is actually 22968714, so it has to walk the entire index or table to get to the value passed and do the comparison of VisitLogID + adminID. However, in the second query, both are hard-coded, known values, so the optimizer is choosing the best possible path.
You could add an index hint on the first one to help the optimizer along. You might also see what the results are if you make the adminID a variable instead. It's possible the optimizer may have better results with that one, too.
And, of course, check your indexes. If you have an index only on VisitLogID, but not on adminID, or only on adminID, but not on VisitLogID, you may run into table scans, which are slower. Even index scans are slower. What you really want to see is an index seek. You may even want a multi-column index, in which case, I'd recommend adminID, VisitLogID, in that order, then change your query to match the order (e.g.: select top 25 * from LogOfPageViews where adminID = 188 and VisitLogID = @id). That last bit of advice about changing the query to match is from the olden days of SQL Server. Not sure if newer versions need this particular manual optimization anymore. It's an old habit of mine to do it this way when possible.
Also, to help you find the issue, when running in SSMS, make sure you turn on the Display Actual Execution Plan. That will show you where the query is spending its time, and you can see from the higher percentages where the bottleneck(s) are.